Index: code/trunk/src/audio/AudioPrereqs.h
===================================================================
--- code/trunk/src/audio/AudioPrereqs.h	(revision 1407)
+++ code/trunk/src/audio/AudioPrereqs.h	(revision 1502)
@@ -35,5 +35,5 @@
 #define _AudioPrereqs_H__
 
-#include "OrxonoxPlatform.h"
+#include "util/OrxonoxPlatform.h"
 
 //-----------------------------------------------------------------------
Index: code/trunk/src/audio/AudioStream.cc
===================================================================
--- code/trunk/src/audio/AudioStream.cc	(revision 1407)
+++ code/trunk/src/audio/AudioStream.cc	(revision 1502)
@@ -117,5 +117,7 @@
 
 	    for(int i = 0; i < vorbisComment->comments; i++)
+	    {
 	        COUT(3) << "   " << vorbisComment->user_comments[i] << std::endl;
+	    }
 
 	    COUT(3) << std::endl;
Index: code/trunk/src/core/ArgumentCompleter.h
===================================================================
--- code/trunk/src/core/ArgumentCompleter.h	(revision 1502)
+++ code/trunk/src/core/ArgumentCompleter.h	(revision 1502)
@@ -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 _ArgumentCompleter_H__
+#define _ArgumentCompleter_H__
+
+#include "CorePrereqs.h"
+#include "ArgumentCompletionListElement.h"
+
+namespace orxonox
+{
+    class _CoreExport ArgumentCompleter
+    {
+        public:
+            ArgumentCompleter(ArgumentCompletionList (*function) (void)) : paramCount_(0), function_0_(function) {}
+            ArgumentCompleter(ArgumentCompletionList (*function) (const std::string& param1)) : paramCount_(1), function_1_(function) {}
+            ArgumentCompleter(ArgumentCompletionList (*function) (const std::string& param1, const std::string& param2)) : paramCount_(2), function_2_(function) {}
+            ArgumentCompleter(ArgumentCompletionList (*function) (const std::string& param1, const std::string& param2, const std::string& param3)) : paramCount_(3), function_3_(function) {}
+            ArgumentCompleter(ArgumentCompletionList (*function) (const std::string& param1, const std::string& param2, const std::string& param3, const std::string& param4)) : paramCount_(4), function_4_(function) {}
+            ArgumentCompleter(ArgumentCompletionList (*function) (const std::string& param1, const std::string& param2, const std::string& param3, const std::string& param4, const std::string& param5)) : paramCount_(5), function_5_(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();
+                }
+            }
+
+        private:
+            unsigned char paramCount_;
+            ArgumentCompletionList (*function_0_) (void);
+            ArgumentCompletionList (*function_1_) (const std::string& param1);
+            ArgumentCompletionList (*function_2_) (const std::string& param1, const std::string& param2);
+            ArgumentCompletionList (*function_3_) (const std::string& param1, const std::string& param2, const std::string& param3);
+            ArgumentCompletionList (*function_4_) (const std::string& param1, const std::string& param2, const std::string& param3, const std::string& param4);
+            ArgumentCompletionList (*function_5_) (const std::string& param1, const std::string& param2, const std::string& param3, const std::string& param4, const std::string& param5);
+    };
+}
+
+#endif /* _ArgumentCompleter_H__ */
Index: code/trunk/src/core/ArgumentCompletionFunctions.cc
===================================================================
--- code/trunk/src/core/ArgumentCompletionFunctions.cc	(revision 1502)
+++ code/trunk/src/core/ArgumentCompletionFunctions.cc	(revision 1502)
@@ -0,0 +1,144 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if 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 <iostream>
+#include <map>
+
+#include "boost/filesystem.hpp"
+
+#include "ArgumentCompletionFunctions.h"
+#include "CoreIncludes.h"
+#include "Identifier.h"
+#include "ConfigValueContainer.h"
+#include "TclThreadManager.h"
+#include "util/Convert.h"
+#include "util/String.h"
+
+namespace orxonox
+{
+    namespace autocompletion
+    {
+        ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(fallback)()
+        {
+            return ArgumentCompletionList();
+        }
+
+        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 = ".";
+                }
+#if ORXONOX_PLATFORM == ORXONOX_PLATFORM_WIN32
+                else
+                {
+                    std::string dir = startdirectory.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.push_back(ArgumentCompletionListElement((*file).string() + "/", getLowercase((*file).string()) + "/", (*file).leaf() + "/"));
+                    else
+                        filelist.push_back(ArgumentCompletionListElement((*file).string(), getLowercase((*file).string()), (*file).leaf()));
+                    ++file;
+                }
+            }
+            catch (...) {}
+
+            filelist.insert(filelist.begin(), dirlist.begin(), dirlist.end());
+            return filelist;
+        }
+
+        ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(configvalueclasses)()
+        {
+            ArgumentCompletionList classlist;
+
+            for (std::map<std::string, Identifier*>::const_iterator it = Identifier::getIdentifierMapBegin(); it != Identifier::getIdentifierMapEnd(); ++it)
+                if ((*it).second->hasConfigValues())
+                    classlist.push_back(ArgumentCompletionListElement((*it).second->getName(), getLowercase((*it).first)));
+
+            return classlist;
+        }
+
+        ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(configvalues)(const std::string& fragment, const std::string& classname)
+        {
+            ArgumentCompletionList configvalues;
+            std::map<std::string, Identifier*>::const_iterator identifier = Identifier::getIdentifierMap().find(classname);
+
+            if (identifier != Identifier::getIdentifierMapEnd() && (*identifier).second->hasConfigValues())
+            {
+                for (std::map<std::string, ConfigValueContainer*>::const_iterator it = (*identifier).second->getConfigValueMapBegin(); it != (*identifier).second->getConfigValueMapEnd(); ++it)
+                    configvalues.push_back(ArgumentCompletionListElement((*it).second->getName(), getLowercase((*it).first)));
+            }
+
+            return configvalues;
+        }
+
+        ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(configvalue)(const std::string& fragment, const std::string& varname, const std::string& classname)
+        {
+            ArgumentCompletionList oldvalue;
+            std::map<std::string, Identifier*>::const_iterator identifier = Identifier::getLowercaseIdentifierMap().find(getLowercase(classname));
+            if (identifier != Identifier::getLowercaseIdentifierMapEnd())
+            {
+                std::map<std::string, ConfigValueContainer*>::const_iterator variable = (*identifier).second->getLowercaseConfigValueMap().find(getLowercase(varname));
+                if (variable != (*identifier).second->getLowercaseConfigValueMapEnd())
+                {
+                    std::string valuestring = (*variable).second->toString();
+                    oldvalue.push_back(ArgumentCompletionListElement(valuestring, getLowercase(valuestring), "Old value: " + valuestring));
+                }
+            }
+            return oldvalue;
+        }
+
+        ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(tclthreads)()
+        {
+            std::list<unsigned int> threadnumbers = TclThreadManager::getInstance().getThreadList();
+            ArgumentCompletionList threads;
+
+            for (std::list<unsigned int>::const_iterator it = threadnumbers.begin(); it != threadnumbers.end(); ++it)
+                threads.push_back(ArgumentCompletionListElement(getConvertedValue<unsigned int, std::string>(*it)));
+
+            return threads;
+        }
+    }
+}
Index: code/trunk/src/core/ArgumentCompletionFunctions.h
===================================================================
--- code/trunk/src/core/ArgumentCompletionFunctions.h	(revision 1502)
+++ code/trunk/src/core/ArgumentCompletionFunctions.h	(revision 1502)
@@ -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 _ArgumentCompletionFunctions_H__
+#define _ArgumentCompletionFunctions_H__
+
+#include "CorePrereqs.h"
+#include "ArgumentCompleter.h"
+
+
+#define ARGUMENT_COMPLETION_FUNCTION_DECLARATION(functionname) \
+    ArgumentCompleter* functionname(); \
+    _CoreExport ArgumentCompletionList acf_##functionname
+
+#define ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(functionname) \
+    ArgumentCompleter* functionname() \
+    { \
+        static ArgumentCompleter completer = ArgumentCompleter(&acf_##functionname); \
+        return &completer; \
+    } \
+    \
+    ArgumentCompletionList acf_##functionname
+
+
+namespace orxonox
+{
+    namespace autocompletion
+    {
+        ARGUMENT_COMPLETION_FUNCTION_DECLARATION(fallback)();
+        ARGUMENT_COMPLETION_FUNCTION_DECLARATION(files)(const std::string& fragment);
+        ARGUMENT_COMPLETION_FUNCTION_DECLARATION(configvalueclasses)();
+        ARGUMENT_COMPLETION_FUNCTION_DECLARATION(configvalues)(const std::string& fragment, const std::string& classname);
+        ARGUMENT_COMPLETION_FUNCTION_DECLARATION(configvalue)(const std::string& fragment, const std::string& varname, const std::string& classname);
+        ARGUMENT_COMPLETION_FUNCTION_DECLARATION(tclthreads)();
+    }
+}
+
+#endif /* _ArgumentCompletionFunctions_H__ */
Index: code/trunk/src/core/ArgumentCompletionListElement.h
===================================================================
--- code/trunk/src/core/ArgumentCompletionListElement.h	(revision 1502)
+++ code/trunk/src/core/ArgumentCompletionListElement.h	(revision 1502)
@@ -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:
+ *      ...
+ *
+ */
+
+#ifndef _ArgumentCompletionListElement_H__
+#define _ArgumentCompletionListElement_H__
+
+#include "CorePrereqs.h"
+
+#include <string>
+#include <list>
+
+#define ACL_MODE_NORMAL    1
+#define ACL_MODE_LOWERCASE 2
+#define ACL_MODE_DISPLAY   4
+
+namespace orxonox
+{
+    typedef std::list<ArgumentCompletionListElement> ArgumentCompletionList;
+
+    class _CoreExport ArgumentCompletionListElement
+    {
+        public:
+            ArgumentCompletionListElement(const std::string& normalcase) : mode_(ACL_MODE_NORMAL), normalCase_(normalcase) {}
+            ArgumentCompletionListElement(const std::string& normalcase, const std::string& lowercase) : mode_(ACL_MODE_NORMAL | ACL_MODE_LOWERCASE), normalCase_(normalcase), lowerCase_(lowercase) {}
+            ArgumentCompletionListElement(const std::string& normalcase, const std::string& lowercase, const std::string& display) : mode_(ACL_MODE_NORMAL | ACL_MODE_LOWERCASE | ACL_MODE_DISPLAY), normalCase_(normalcase), lowerCase_(lowercase), display_(display) {}
+
+            const std::string& getString() const
+                { return this->normalCase_; }
+            const std::string& getComparable() const
+                { if (this->mode_ & ACL_MODE_LOWERCASE) { return this->lowerCase_; } else { return this->normalCase_; } }
+            const std::string& getDisplay() const
+                { if (this->mode_ & ACL_MODE_DISPLAY) { return this->display_; } else { return this->normalCase_; } }
+
+            bool lowercaseComparison() const
+                { return (this->mode_ & ACL_MODE_LOWERCASE); }
+
+            bool operator<(const ArgumentCompletionListElement& other) const
+                { return (this->getComparable() < other.getComparable()); }
+
+        private:
+            unsigned char mode_;
+            std::string normalCase_;
+            std::string lowerCase_;
+            std::string display_;
+    };
+}
+
+#endif /* _ArgumentCompletionListElement_H__ */
Index: code/trunk/src/core/CMakeLists.txt
===================================================================
--- code/trunk/src/core/CMakeLists.txt	(revision 1407)
+++ code/trunk/src/core/CMakeLists.txt	(revision 1502)
@@ -2,5 +2,4 @@
   BaseObject.cc
   ClassTreeMask.cc
-  CommandExecutor.cc
   ConfigFileManager.cc
   ConfigValueContainer.cc
@@ -11,7 +10,14 @@
   Identifier.cc
   IdentifierDistributor.cc
+  InputManager.cc
+  KeyBinder.cc
+  OutputBuffer.cc
   InputBuffer.cc
-  InputHandler.cc
-  InputManager.cc
+  Shell.cc
+  CommandExecutor.cc
+  CommandEvaluation.cc
+  ConsoleCommand.cc
+  ArgumentCompletionFunctions.cc
+  ConsoleCommandCompilation.cc
   Language.cc
   Loader.cc
@@ -26,4 +32,6 @@
   Tickable.cc
   XMLPort.cc
+  TclThreadManager.cc
+  IRC.cc
   tolua/tolua_bind.cc
 )
@@ -47,3 +55,5 @@
   ois
   util
+  ${Boost_thread_LIBRARIES}
+  ${Boost_filesystem_LIBRARIES}
 )
Index: code/trunk/src/core/ClassManager.h
===================================================================
--- code/trunk/src/core/ClassManager.h	(revision 1407)
+++ code/trunk/src/core/ClassManager.h	(revision 1502)
@@ -49,4 +49,5 @@
 #include "Identifier.h"
 #include "IdentifierDistributor.h"
+#include "Debug.h"
 
 namespace orxonox
Index: code/trunk/src/core/CommandEvaluation.cc
===================================================================
--- code/trunk/src/core/CommandEvaluation.cc	(revision 1502)
+++ code/trunk/src/core/CommandEvaluation.cc	(revision 1502)
@@ -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:
+ *      ...
+ *
+ */
+
+#include "CommandEvaluation.h"
+#include "ConsoleCommand.h"
+#include "Debug.h"
+#include "util/String.h"
+
+namespace orxonox
+{
+    CommandEvaluation::CommandEvaluation()
+    {
+        this->initialize("");
+        this->state_ = CS_Uninitialized;
+    }
+
+    void CommandEvaluation::initialize(const std::string& command)
+    {
+        this->bNewCommand_ = true;
+        this->bCommandChanged_ = false;
+        this->originalCommand_ = command;
+        this->command_ = command;
+        this->commandTokens_.split(command, " ", SubString::WhiteSpaces, false, '\\', false, '"', false, '(', ')', false, '\0');
+
+        this->additionalParameter_ = "";
+
+        this->bEvaluatedParams_ = false;
+
+        this->listOfPossibleIdentifiers_.clear();
+        this->listOfPossibleFunctions_.clear();
+        this->listOfPossibleArguments_.clear();
+
+        this->functionclass_ = 0;
+        this->function_ = 0;
+        this->possibleArgument_ = "";
+        this->argument_ = "";
+
+        this->errorMessage_ = "";
+        this->state_ = CS_Empty;
+    }
+
+    bool CommandEvaluation::isValid() const
+    {
+        return (this->function_);
+    }
+
+    bool CommandEvaluation::execute() const
+    {
+        if (!this->isValid())
+            return false;
+
+        if (this->bEvaluatedParams_ && this->function_)
+        {
+            COUT(4) << "CE_execute (evaluation): " << this->function_->getName() << " " << this->param_[0] << " " << this->param_[1] << " " << this->param_[2] << " " << this->param_[3] << " " << this->param_[4] << std::endl;
+            (*this->function_)(this->param_[0], this->param_[1], this->param_[2], this->param_[3], this->param_[4]);
+            return true;
+        }
+
+        if (!this->bCommandChanged_ || removeTrailingWhitespaces(this->command_) == removeTrailingWhitespaces(this->originalCommand_))
+        {
+            COUT(4) << "CE_execute: " << this->command_ << "\n";
+
+            unsigned int startindex = this->getStartindex();
+            if (this->commandTokens_.size() > startindex)
+                return this->function_->parse(removeSlashes(this->commandTokens_.subSet(startindex).join() + this->getAdditionalParameter()));
+            else
+                return this->function_->parse(removeSlashes(this->additionalParameter_));
+        }
+
+        return false;
+    }
+
+    std::string CommandEvaluation::complete()
+    {
+        if (!this->bNewCommand_)
+        {
+            switch (this->state_)
+            {
+                case CS_Uninitialized:
+                    break;
+                case CS_Empty:
+                    break;
+                case CS_ShortcutOrIdentifier:
+                    if (this->function_)
+                    {
+                        if (this->function_->getParamCount() == 0)
+                            return (this->command_ = this->function_->getName());
+                        else
+                            return (this->command_ = this->function_->getName() + " ");
+                    }
+                    else if (this->functionclass_)
+                        return (this->command_ = this->functionclass_->getName() + " ");
+                    break;
+                case CS_Function:
+                    if (this->function_)
+                    {
+                        if (this->function_->getParamCount() == 0)
+                            return (this->command_ = this->functionclass_->getName() + " " + this->function_->getName());
+                        else
+                            return (this->command_ = this->functionclass_->getName() + " " + this->function_->getName() + " ");
+                    }
+                    break;
+                case CS_ParamPreparation:
+                case CS_Params:
+                {
+                    if (this->argument_ == "" && this->possibleArgument_ == "")
+                        break;
+
+                    unsigned int maxIndex = this->commandTokens_.size();
+                    if (this->command_[this->command_.size() - 1] != ' ')
+                        maxIndex -= 1;
+                    std::string whitespace = "";
+
+                    if (this->possibleArgument_ != "")
+                    {
+                        this->argument_ = this->possibleArgument_;
+                        if (this->function_->getParamCount() > (maxIndex + 1 - this->getStartindex()))
+                            whitespace = " ";
+                    }
+
+                    return (this->command_ = this->commandTokens_.subSet(0, maxIndex).join() + " " + this->argument_ + whitespace);
+                    break;
+                }
+                case CS_Finished:
+                    break;
+                case CS_Error:
+                    break;
+            }
+        }
+        this->bNewCommand_ = false;
+        return this->command_;
+    }
+
+    std::string CommandEvaluation::hint() const
+    {
+        switch (this->state_)
+        {
+            case CS_Uninitialized:
+                break;
+            case CS_Empty:
+            case CS_ShortcutOrIdentifier:
+                if (this->listOfPossibleFunctions_.size() == 0)
+                    return CommandEvaluation::dump(this->listOfPossibleIdentifiers_);
+                else if (this->listOfPossibleIdentifiers_.size() == 0)
+                    return CommandEvaluation::dump(this->listOfPossibleFunctions_);
+                else
+                    return (CommandEvaluation::dump(this->listOfPossibleFunctions_) + "\n" + CommandEvaluation::dump(this->listOfPossibleIdentifiers_));
+                break;
+            case CS_Function:
+                return CommandEvaluation::dump(this->listOfPossibleFunctions_);
+                break;
+            case CS_ParamPreparation:
+            case CS_Params:
+                if (this->listOfPossibleArguments_.size() > 0)
+                    return CommandEvaluation::dump(this->listOfPossibleArguments_);
+                else
+                    return CommandEvaluation::dump(this->function_);
+            case CS_Finished:
+                if (this->function_)
+                    return CommandEvaluation::dump(this->function_);
+                break;
+            case CS_Error:
+                return this->errorMessage_;
+                break;
+        }
+
+        return "";
+    }
+
+    void CommandEvaluation::evaluateParams()
+    {
+        this->bEvaluatedParams_ = false;
+
+        for (unsigned int i = 0; i < MAX_FUNCTOR_ARGUMENTS; i++)
+            this->param_[i] = MT_null;
+
+        if (!this->isValid())
+            return;
+
+        unsigned int startindex = this->getStartindex();
+
+        if (this->commandTokens_.size() <= startindex)
+        {
+            if (this->function_->evaluate(this->getAdditionalParameter(), this->param_, " "))
+                this->bEvaluatedParams_ = true;
+        }
+        else if (this->commandTokens_.size() > startindex)
+        {
+            if (this->function_->evaluate(this->commandTokens_.subSet(startindex).join() + this->getAdditionalParameter(), this->param_, " "))
+                this->bEvaluatedParams_ = true;
+        }
+    }
+
+    void CommandEvaluation::setEvaluatedParameter(unsigned int index, MultiTypeMath param)
+    {
+        if (index >= 0 && index < MAX_FUNCTOR_ARGUMENTS)
+            this->param_[index] = param;
+    }
+
+    MultiTypeMath CommandEvaluation::getEvaluatedParameter(unsigned int index) const
+    {
+        if (index >= 0 && index < MAX_FUNCTOR_ARGUMENTS)
+            return this->param_[index];
+
+        return MT_null;
+    }
+
+    bool CommandEvaluation::hasReturnvalue() const
+    {
+        if (this->function_)
+            return this->function_->hasReturnvalue();
+
+        return MT_null;
+    }
+
+    MultiTypeMath CommandEvaluation::getReturnvalue() const
+    {
+        if (this->function_)
+            return this->function_->getReturnvalue();
+
+        return MultiTypeMath();
+    }
+
+
+    unsigned int CommandEvaluation::getStartindex() const
+    {
+        if (this->functionclass_ && this->function_)
+            return 2;
+        else if (this->function_)
+            return 1;
+        else
+            return 0;
+    }
+
+    std::string CommandEvaluation::dump(const std::list<std::pair<const std::string*, const std::string*> >& list)
+    {
+        std::string output = "";
+        for (std::list<std::pair<const std::string*, const std::string*> >::const_iterator it = list.begin(); it != list.end(); ++it)
+        {
+            if (it != list.begin())
+                output += " ";
+
+            output += *(*it).second;
+        }
+        return output;
+    }
+
+    std::string CommandEvaluation::dump(const ArgumentCompletionList& list)
+    {
+        std::string output = "";
+        for (ArgumentCompletionList::const_iterator it = list.begin(); it != list.end(); ++it)
+        {
+            if (it != list.begin())
+                output += " ";
+
+            output += (*it).getDisplay();
+        }
+        return output;
+    }
+
+    std::string CommandEvaluation::dump(const ConsoleCommand* command)
+    {
+        std::string output = command->getName();
+        if (command->getParamCount() > 0)
+            output += ": ";
+
+        for (unsigned int i = 0; i < command->getParamCount(); i++)
+        {
+            if (i != 0)
+                output += " ";
+
+            if (command->defaultValueSet(i))
+                output += "[";
+            else
+                output += "{";
+
+            output += command->getTypenameParam(i);
+
+            if (command->defaultValueSet(i))
+                output += "=" + command->getDefaultValue(i).toString() + "]";
+            else
+                output += "}";
+        }
+        return output;
+    }
+}
Index: code/trunk/src/core/CommandEvaluation.h
===================================================================
--- code/trunk/src/core/CommandEvaluation.h	(revision 1502)
+++ code/trunk/src/core/CommandEvaluation.h	(revision 1502)
@@ -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:
+ *      ...
+ *
+ */
+
+#ifndef _CommandEvaluation_H__
+#define _CommandEvaluation_H__
+
+#include "CorePrereqs.h"
+
+#include <string>
+#include <list>
+
+#include "ArgumentCompletionListElement.h"
+#include "util/SubString.h"
+#include "util/MultiTypeMath.h"
+
+namespace orxonox
+{
+    enum CommandState
+    {
+        CS_Uninitialized,
+        CS_Empty,
+        CS_ShortcutOrIdentifier,
+        CS_Function,
+        CS_ParamPreparation,
+        CS_Params,
+        CS_Finished,
+        CS_Error
+    };
+
+    class _CoreExport CommandEvaluation
+    {
+        friend class CommandExecutor;
+
+        public:
+            CommandEvaluation();
+
+            void initialize(const std::string& command);
+
+            bool execute() const;
+            std::string complete();
+            std::string hint() const;
+            void evaluateParams();
+
+            bool isValid() const;
+
+            inline ConsoleCommand* getConsoleCommand() const
+                { return this->function_; }
+            inline const std::string& getOriginalCommand() const
+                { return this->originalCommand_; }
+            inline const std::string& getCommand() const
+                { return this->command_; }
+
+            inline void setAdditionalParameter(const std::string& param)
+                { this->additionalParameter_ = param; this->bEvaluatedParams_ = false; }
+            inline std::string getAdditionalParameter() const
+                { return (this->additionalParameter_ != "") ? (" " + this->additionalParameter_) : ""; }
+
+            void setEvaluatedParameter(unsigned int index, MultiTypeMath param);
+            MultiTypeMath getEvaluatedParameter(unsigned int index) const;
+
+            bool hasReturnvalue() const;
+            MultiTypeMath getReturnvalue() const;
+
+        private:
+            unsigned int getStartindex() const;
+            static std::string dump(const std::list<std::pair<const std::string*, const std::string*> >& list);
+            static std::string dump(const ArgumentCompletionList& list);
+            static std::string dump(const ConsoleCommand* command);
+
+
+            bool bNewCommand_;
+            bool bCommandChanged_;
+
+            std::string originalCommand_;
+            std::string command_;
+            SubString commandTokens_;
+            std::string additionalParameter_;
+
+            std::list<std::pair<const std::string*, const std::string*> > listOfPossibleIdentifiers_;
+            std::list<std::pair<const std::string*, const std::string*> > listOfPossibleFunctions_;
+            ArgumentCompletionList listOfPossibleArguments_;
+
+            Identifier* functionclass_;
+            ConsoleCommand* function_;
+            std::string possibleArgument_;
+            std::string argument_;
+
+            std::string errorMessage_;
+            CommandState state_;
+
+            bool bEvaluatedParams_;
+            MultiTypeMath param_[5];
+    };
+}
+
+#endif /* _CommandEvaluation_H__ */
Index: code/trunk/src/core/CommandExecutor.cc
===================================================================
--- code/trunk/src/core/CommandExecutor.cc	(revision 1407)
+++ code/trunk/src/core/CommandExecutor.cc	(revision 1502)
@@ -31,303 +31,11 @@
 #include "util/String.h"
 #include "util/Convert.h"
-#include "util/SubString.h"
 #include "Identifier.h"
 #include "Language.h"
 #include "Debug.h"
-#include "Executor.h"
-#include "ConfigValueContainer.h"
 #include "TclBind.h"
-
-#define COMMAND_EXECUTOR_KEYWORD_SET_CONFIG_VALUE "set"
-#define COMMAND_EXECUTOR_KEYWORD_SET_CONFIG_VALUE_TEMPORARY "tset"
-#define COMMAND_EXECUTOR_KEYWORD_SET_KEYBIND "bind"
 
 namespace orxonox
 {
-    ConsoleCommandShortcutGeneric(keyword1, createExecutor((FunctorStatic*)0, "set", AccessLevel::User));
-    ConsoleCommandShortcutGeneric(keyword2, createExecutor((FunctorStatic*)0, "tset", AccessLevel::User));
-    ConsoleCommandShortcutGeneric(keyword3, createExecutor((FunctorStatic*)0, "bind", AccessLevel::User));
-
-    ConsoleCommandShortcutExtern(exec, AccessLevel::None);
-    ConsoleCommandShortcutExtern(echo, AccessLevel::None);
-
-    ConsoleCommandShortcutExtern(read, AccessLevel::None);
-    ConsoleCommandShortcutExtern(append, AccessLevel::None);
-    ConsoleCommandShortcutExtern(write, AccessLevel::None);
-
-    void exec(const std::string& filename)
-    {
-        static std::set<std::string> executingFiles;
-
-        std::set<std::string>::const_iterator it = executingFiles.find(filename);
-        if (it != executingFiles.end())
-        {
-            COUT(1) << "Error: Recurring exec command in \"" << filename << "\". Stopped execution." << std::endl;
-            return;
-        }
-
-        // Open the file
-        std::ifstream file;
-        file.open(filename.c_str(), std::fstream::in);
-
-        if (!file.is_open())
-        {
-            COUT(1) << "Error: Couldn't execute file \"" << filename << "\"." << std::endl;
-            return;
-        }
-
-        executingFiles.insert(filename);
-
-        // Iterate through the file and put the lines into the CommandExecutor
-        char line[1024];
-        while (file.good() && !file.eof())
-        {
-            file.getline(line, 1024);
-            CommandExecutor::execute(line);
-        }
-
-        executingFiles.erase(filename);
-        file.close();
-    }
-
-    std::string echo(const std::string& text)
-    {
-        return text;
-    }
-
-    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())
-        {
-            COUT(1) << "Error: Couldn't write to file \"" << filename << "\"." << std::endl;
-            return;
-        }
-
-        file << text << std::endl;
-        file.close();
-    }
-
-    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())
-        {
-            COUT(1) << "Error: Couldn't append to file \"" << filename << "\"." << std::endl;
-            return;
-        }
-
-        file << text << std::endl;
-        file.close();
-    }
-
-    std::string read(const std::string& filename)
-    {
-        std::ifstream file;
-        file.open(filename.c_str(), std::fstream::in);
-
-        if (!file.is_open())
-        {
-            COUT(1) << "Error: Couldn't read from file \"" << filename << "\"." << std::endl;
-            return "";
-        }
-
-        std::string output = "";
-        char line[1024];
-        while (file.good() && !file.eof())
-        {
-            file.getline(line, 1024);
-            output += line;
-            output += "\n";
-        }
-
-        file.close();
-
-        return output;
-    }
-
-
-    ///////////////////////
-    // CommandEvaluation //
-    ///////////////////////
-    CommandEvaluation::CommandEvaluation()
-    {
-        this->processedCommand_ = "";
-        this->additionalParameter_ = "";
-
-        this->functionclass_ = 0;
-        this->configvalueclass_ = 0;
-        this->shortcut_ = 0;
-        this->function_ = 0;
-        this->configvalue_ = 0;
-        this->key_ = 0;
-
-        this->errorMessage_ = "";
-        this->state_ = CS_Uninitialized;
-
-        this->bEvaluatedParams_ = false;
-        this->evaluatedExecutor_ = 0;
-    }
-
-    KeybindMode::Enum CommandEvaluation::getKeybindMode()
-    {
-        if (this->state_ == CS_Shortcut_Params || this->state_ == CS_Shortcut_Finished)
-        {
-//            if (this->shortcut_ != 0)
-//                return this->shortcut_->getKeybindMode();
-        }
-        else if (this->state_ == CS_Function_Params || this->state_ == CS_Function_Finished)
-        {
-//            if (this->function_ != 0)
-//                return this->function_->getKeybindMode();
-        }
-        else if (this->state_ == CS_ConfigValueType || this->state_ == CS_ConfigValueFinished)
-        {
-//            return KeybindMode::onPress;
-        }
-        else if (this->state_ == CS_KeybindCommand || this->state_ == CS_KeybindFinished)
-        {
-//            return KeybindMode::onPress;
-        }
-        else
-        {
-//            return KeybindMode::onPress;
-        }
-        // FIXME: Had to insert a return statement
-        return (KeybindMode::Enum)0;
-    }
-
-    bool CommandEvaluation::isValid() const
-    {
-        if (this->state_ == CS_Shortcut_Params || this->state_ == CS_Shortcut_Finished)
-        {
-            return this->shortcut_;
-        }
-        else if (this->state_ == CS_Function_Params || this->state_ == CS_Function_Finished)
-        {
-            return (this->functionclass_ && this->function_);
-        }
-        else if (this->state_ == CS_ConfigValueType || this->state_ == CS_ConfigValueFinished)
-        {
-            return (this->configvalueclass_ && this->configvalue_);
-        }
-        else if (this->state_ == CS_KeybindCommand || this->state_ == CS_KeybindFinished)
-        {
-            return this->key_;
-        }
-        else
-        {
-            return false;
-        }
-    }
-
-    void CommandEvaluation::evaluateParams()
-    {
-        this->bEvaluatedParams_ = false;
-        this->evaluatedExecutor_ = 0;
-
-        for (unsigned int i = 0; i < MAX_FUNCTOR_ARGUMENTS; i++)
-            this->param_[i] = MT_null;
-
-        if (this->state_ == CS_Shortcut_Params || this->state_ == CS_Shortcut_Finished)
-        {
-            if (this->shortcut_)
-            {
-                if (this->tokens_.size() <= 1)
-                {
-                    if (this->shortcut_->evaluate(this->getAdditionalParameter(), this->param_, " "))
-                    {
-                        this->bEvaluatedParams_ = true;
-                        this->evaluatedExecutor_ = this->shortcut_;
-                    }
-                }
-                else if (this->tokens_.size() > 1)
-                {
-                    if (this->shortcut_->evaluate(this->tokens_.subSet(1).join() + this->getAdditionalParameter(), this->param_, " "))
-                    {
-                        this->bEvaluatedParams_ = true;
-                        this->evaluatedExecutor_ = this->shortcut_;
-                    }
-                }
-            }
-        }
-        else if (this->state_ == CS_Function_Params || this->state_ == CS_Function_Finished)
-        {
-            if (this->function_)
-            {
-                if (this->tokens_.size() <= 2)
-                {
-                    if (this->function_->evaluate(this->getAdditionalParameter(), this->param_, " "))
-                    {
-                        this->bEvaluatedParams_ = true;
-                        this->evaluatedExecutor_ = this->function_;
-                    }
-                }
-                else if (this->tokens_.size() > 2)
-                {
-                    if (this->function_->evaluate(this->tokens_.subSet(2).join() + this->getAdditionalParameter(), this->param_, " "))
-                    {
-                        this->bEvaluatedParams_ = true;
-                        this->evaluatedExecutor_ = this->function_;
-                    }
-                }
-            }
-        }
-    }
-
-    void CommandEvaluation::setEvaluatedParameter(unsigned int index, MultiTypeMath param)
-    {
-        if (index >= 0 && index < MAX_FUNCTOR_ARGUMENTS)
-            this->param_[index] = param;
-    }
-
-    MultiTypeMath CommandEvaluation::getEvaluatedParameter(unsigned int index) const
-    {
-        if (index >= 0 && index < MAX_FUNCTOR_ARGUMENTS)
-            return this->param_[index];
-
-        return MT_null;
-    }
-
-    bool CommandEvaluation::hasReturnvalue() const
-    {
-        if (this->state_ == CS_Shortcut_Params || this->state_ == CS_Shortcut_Finished)
-        {
-            if (this->shortcut_)
-                return this->shortcut_->hasReturnvalue();
-        }
-        else if (this->state_ == CS_Function_Params || this->state_ == CS_Function_Finished)
-        {
-            if (this->function_)
-                return this->function_->hasReturnvalue();
-        }
-
-        return MT_null;
-    }
-
-    MultiTypeMath CommandEvaluation::getReturnvalue() const
-    {
-        if (this->state_ == CS_Shortcut_Params || this->state_ == CS_Shortcut_Finished)
-        {
-            if (this->shortcut_)
-                return this->shortcut_->getReturnvalue();
-        }
-        else if (this->state_ == CS_Function_Params || this->state_ == CS_Function_Finished)
-        {
-            if (this->function_)
-                return this->function_->getReturnvalue();
-        }
-
-        return MT_null;
-    }
-
-
-    /////////////////////
-    // CommandExecutor //
-    /////////////////////
     CommandExecutor& CommandExecutor::getInstance()
     {
@@ -346,9 +54,16 @@
     }
 
-    Executor& CommandExecutor::addConsoleCommandShortcut(ExecutorStatic* executor)
-    {
-        CommandExecutor::getInstance().consoleCommandShortcuts_[executor->getName()] = executor;
-        CommandExecutor::getInstance().consoleCommandShortcuts_LC_[getLowercase(executor->getName())] = executor;
-        return (*executor);
+    ConsoleCommand& CommandExecutor::addConsoleCommandShortcut(ConsoleCommand* command)
+    {
+        std::map<std::string, ConsoleCommand*>::const_iterator it = CommandExecutor::getInstance().consoleCommandShortcuts_.find(command->getName());
+        if (it != CommandExecutor::getInstance().consoleCommandShortcuts_.end())
+        {
+            COUT(2) << "Warning: Overwriting console-command shortcut with name " << command->getName() << "." << std::endl;
+        }
+
+
+        CommandExecutor::getInstance().consoleCommandShortcuts_[command->getName()] = command;
+        CommandExecutor::getInstance().consoleCommandShortcuts_LC_[getLowercase(command->getName())] = command;
+        return (*command);
     }
 
@@ -358,7 +73,7 @@
         @return The executor of the requested console command shortcut
     */
-    ExecutorStatic* CommandExecutor::getConsoleCommandShortcut(const std::string& name)
-    {
-        std::map<std::string, ExecutorStatic*>::const_iterator it = CommandExecutor::getInstance().consoleCommandShortcuts_.find(name);
+    ConsoleCommand* CommandExecutor::getConsoleCommandShortcut(const std::string& name)
+    {
+        std::map<std::string, ConsoleCommand*>::const_iterator it = CommandExecutor::getInstance().consoleCommandShortcuts_.find(name);
         if (it != CommandExecutor::getInstance().consoleCommandShortcuts_.end())
             return (*it).second;
@@ -372,7 +87,7 @@
         @return The executor of the requested console command shortcut
     */
-    ExecutorStatic* CommandExecutor::getLowercaseConsoleCommandShortcut(const std::string& name)
-    {
-        std::map<std::string, ExecutorStatic*>::const_iterator it = CommandExecutor::getInstance().consoleCommandShortcuts_LC_.find(name);
+    ConsoleCommand* CommandExecutor::getLowercaseConsoleCommandShortcut(const std::string& name)
+    {
+        std::map<std::string, ConsoleCommand*>::const_iterator it = CommandExecutor::getInstance().consoleCommandShortcuts_LC_.find(name);
         if (it != CommandExecutor::getInstance().consoleCommandShortcuts_LC_.end())
             return (*it).second;
@@ -384,866 +99,407 @@
     {
         if (useTcl)
-        {
             return TclBind::eval(command);
-        }
-        else
-        {
-            if ((CommandExecutor::getEvaluation().processedCommand_ != command) || (CommandExecutor::getEvaluation().state_ == CS_Uninitialized))
-                CommandExecutor::parse(command);
-
-            return CommandExecutor::execute(CommandExecutor::getEvaluation());
-        }
-    }
-
-
-    bool CommandExecutor::execute(const CommandEvaluation& evaluation)
-    {
-        SubString tokens(evaluation.processedCommand_, " ", SubString::WhiteSpaces, false, '\\', false, '"', false, '(', ')', false, '\0');
-
-        if (evaluation.bEvaluatedParams_ && evaluation.evaluatedExecutor_)
-        {
-std::cout << "CE_execute (evaluation): " << evaluation.evaluatedExecutor_->getName() << " " << evaluation.param_[0] << " " << evaluation.param_[1] << " " << evaluation.param_[2] << " " << evaluation.param_[3] << " " << evaluation.param_[4] << std::endl;
-            (*evaluation.evaluatedExecutor_)(evaluation.param_[0], evaluation.param_[1], evaluation.param_[2], evaluation.param_[3], evaluation.param_[4]);
-            return true;
-        }
-
-std::cout << "CE_execute: " << evaluation.processedCommand_ << "\n";
-        switch (evaluation.state_)
-        {
-            case CS_Uninitialized:
-                break;
-            case CS_Empty:
-                break;
-            case CS_FunctionClass_Or_Shortcut_Or_Keyword:
-                break;
-            case CS_Shortcut_Params:
-                // not enough parameters but lets hope there are some additional parameters and go on
-            case CS_Shortcut_Finished:
-                // call the shortcut
-                if (evaluation.shortcut_)
-                {
-                    if (tokens.size() >= 2)
-                        return evaluation.shortcut_->parse(removeSlashes(tokens.subSet(1).join() + evaluation.getAdditionalParameter()));
-                    else
-                        return evaluation.shortcut_->parse(removeSlashes(evaluation.additionalParameter_));
-                }
-                break;
-            case CS_Function:
-                break;
-            case CS_Function_Params:
-                // not enough parameters but lets hope there are some additional parameters and go on
-            case CS_Function_Finished:
-                // call the shortcut
-                if (evaluation.function_)
-                {
-                    if (tokens.size() >= 3)
-                        return evaluation.function_->parse(removeSlashes(tokens.subSet(2).join() + evaluation.getAdditionalParameter()));
-                    else
-                        return evaluation.function_->parse(removeSlashes(evaluation.additionalParameter_));
-                }
-                break;
-            case CS_ConfigValueClass:
-                break;
-            case CS_ConfigValue:
-                break;
-            case CS_ConfigValueType:
-                // not enough parameters but lets hope there are some additional parameters and go on
-            case CS_ConfigValueFinished:
-                // set the config value
-                if (evaluation.configvalue_)
-                {
-                    if ((tokens.size() >= 1) && (tokens[0] == COMMAND_EXECUTOR_KEYWORD_SET_CONFIG_VALUE))
-                    {
-                        if (tokens.size() >= 4)
-                            return evaluation.configvalue_->set(removeSlashes(tokens.subSet(3).join() + evaluation.getAdditionalParameter()));
-                        else
-                            return evaluation.configvalue_->set(removeSlashes(evaluation.additionalParameter_));
-                    }
-                    else if ((tokens.size() >= 1) && (tokens[0] == COMMAND_EXECUTOR_KEYWORD_SET_CONFIG_VALUE_TEMPORARY))
-                    {
-                        if (tokens.size() >= 4)
-                            return evaluation.configvalue_->tset(removeSlashes(tokens.subSet(3).join() + evaluation.getAdditionalParameter()));
-                        else
-                            return evaluation.configvalue_->tset(removeSlashes(evaluation.additionalParameter_));
-                    }
-                }
-                break;
-            case CS_KeybindKey:
-                break;
-            case CS_KeybindCommand:
-                // not enough parameters but lets hope there are some additional parameters and go on
-            case CS_KeybindFinished:
-                // set the keybind
-                // ...todo
-                break;
-            case CS_Error:
-                break;
-        }
-
-        return false;
+
+        CommandExecutor::parseIfNeeded(command);
+        return CommandExecutor::getEvaluation().execute();
     }
 
     std::string CommandExecutor::complete(const std::string& command)
     {
-        if ((CommandExecutor::getEvaluation().processedCommand_ != command) || (CommandExecutor::getEvaluation().state_ == CS_Uninitialized))
-            CommandExecutor::parse(command);
-
-        return CommandExecutor::complete(CommandExecutor::getEvaluation());
-    }
-
-    std::string CommandExecutor::complete(const CommandEvaluation& evaluation)
-    {
-        SubString tokens(evaluation.processedCommand_, " ", SubString::WhiteSpaces, false, '\\', false, '"', false, '(', ')', false, '\0');
-
-        std::list<std::pair<const std::string*, const std::string*> > temp;
-        if (evaluation.state_ == CS_Empty)
-        {
-            temp.insert(temp.end(), evaluation.listOfPossibleShortcuts_.begin(), evaluation.listOfPossibleShortcuts_.end());
-            temp.insert(temp.end(), evaluation.listOfPossibleFunctionClasses_.begin(), evaluation.listOfPossibleFunctionClasses_.end());
-        }
-
-        switch (evaluation.state_)
-        {
-            case CS_Uninitialized:
-                break;
-            case CS_Empty:
-                return (CommandExecutor::getCommonBegin(temp));
-                break;
-            case CS_FunctionClass_Or_Shortcut_Or_Keyword:
-                break;
-            case CS_Shortcut_Params:
-                if (evaluation.shortcut_)
-                    return (evaluation.shortcut_->getName() + " ");
-                break;
-            case CS_Shortcut_Finished:
-                if (evaluation.shortcut_)
-                {
-                    if (evaluation.shortcut_->getParamCount() == 0)
-                        return (evaluation.shortcut_->getName());
-                    else if (tokens.size() >= 2)
-                        return (evaluation.shortcut_->getName() + " " + tokens.subSet(1).join());
-                }
-                break;
-            case CS_Function:
-                if (evaluation.functionclass_)
-                    return (evaluation.functionclass_->getName() + " " + CommandExecutor::getCommonBegin(evaluation.listOfPossibleFunctions_));
-                break;
-            case CS_Function_Params:
-                if (evaluation.functionclass_ && evaluation.function_)
-                    return (evaluation.functionclass_->getName() + " " + evaluation.function_->getName() + " ");
-                break;
-            case CS_Function_Finished:
-                if (evaluation.functionclass_ && evaluation.function_)
-                {
-                    if (evaluation.function_->getParamCount() == 0)
-                        return (evaluation.functionclass_->getName() + " " + evaluation.function_->getName());
-                    else if (tokens.size() >= 3)
-                        return (evaluation.functionclass_->getName() + " " + evaluation.function_->getName() + " " + tokens.subSet(2).join());
-                }
-                break;
-            case CS_ConfigValueClass:
-                if (tokens.size() >= 1)
-                    return (tokens[0] + " " + CommandExecutor::getCommonBegin(evaluation.listOfPossibleConfigValueClasses_));
-                break;
-            case CS_ConfigValue:
-                if ((tokens.size() >= 1) && evaluation.configvalueclass_)
-                    return (tokens[0] + " " + evaluation.configvalueclass_->getName() + " " + CommandExecutor::getCommonBegin(evaluation.listOfPossibleConfigValues_));
-                break;
-            case CS_ConfigValueType:
-                if ((tokens.size() >= 1) && evaluation.configvalueclass_ && evaluation.configvalue_)
-                    return (tokens[0] + " " + evaluation.configvalueclass_->getName() + " " + evaluation.configvalue_->getName() + " ");
-                break;
-            case CS_ConfigValueFinished:
-                if ((tokens.size() >= 1) && evaluation.configvalueclass_ && evaluation.configvalue_ && (tokens.size() >= 4))
-                    return (tokens[0] + " " + evaluation.configvalueclass_->getName() + " " + evaluation.configvalue_->getName() + " " + tokens.subSet(3).join());
-                break;
-            case CS_KeybindKey:
-                if (tokens.size() >= 1)
-                    return (tokens[0] + " " + CommandExecutor::getCommonBegin(evaluation.listOfPossibleKeys_));
-                break;
-            case CS_KeybindCommand:
-                if ((evaluation.processedCommand_.size() >= 1) && (evaluation.processedCommand_[evaluation.processedCommand_.size() - 1] != ' '))
-                    return (evaluation.processedCommand_ + " ");
-                break;
-            case CS_KeybindFinished:
-                break;
-            case CS_Error:
-                break;
-        }
-
-        return evaluation.processedCommand_;
+        CommandExecutor::parseIfNeeded(command);
+        return CommandExecutor::getEvaluation().complete();
     }
 
     std::string CommandExecutor::hint(const std::string& command)
     {
-        if ((CommandExecutor::getEvaluation().processedCommand_ != command) || (CommandExecutor::getEvaluation().state_ == CS_Uninitialized))
-            CommandExecutor::parse(command);
-
-        return CommandExecutor::hint(CommandExecutor::getEvaluation());
-    }
-
-    std::string CommandExecutor::hint(const CommandEvaluation& evaluation)
-    {
-        SubString tokens(evaluation.processedCommand_, " ", SubString::WhiteSpaces, false, '\\', false, '"', false, '(', ')', false, '\0');
-
-        switch (evaluation.state_)
-        {
-            case CS_Uninitialized:
-                break;
-            case CS_Empty:
-                return (CommandExecutor::dump(evaluation.listOfPossibleShortcuts_) + "\n" + CommandExecutor::dump(evaluation.listOfPossibleFunctionClasses_));
-                break;
-            case CS_FunctionClass_Or_Shortcut_Or_Keyword:
-                break;
-            case CS_Shortcut_Params:
-                if (evaluation.shortcut_)
-                    return CommandExecutor::dump(evaluation.shortcut_);
-                break;
-            case CS_Shortcut_Finished:
-                if (evaluation.shortcut_)
-                    return CommandExecutor::dump(evaluation.shortcut_);
-                break;
-            case CS_Function:
-                return CommandExecutor::dump(evaluation.listOfPossibleFunctions_);
-                break;
-            case CS_Function_Params:
-                if (evaluation.function_)
-                    return CommandExecutor::dump(evaluation.function_);
-                break;
-            case CS_Function_Finished:
-                if (evaluation.function_)
-                    return CommandExecutor::dump(evaluation.function_);
-                break;
-            case CS_ConfigValueClass:
-                return CommandExecutor::dump(evaluation.listOfPossibleConfigValueClasses_);
-                break;
-            case CS_ConfigValue:
-                return CommandExecutor::dump(evaluation.listOfPossibleConfigValues_);
-                break;
-            case CS_ConfigValueType:
-                if (evaluation.configvalue_)
-                    return CommandExecutor::dump(evaluation.configvalue_);
-                break;
-            case CS_ConfigValueFinished:
-                if (evaluation.configvalue_)
-                    return CommandExecutor::dump(evaluation.configvalue_);
-                break;
-            case CS_KeybindKey:
-                return CommandExecutor::dump(evaluation.listOfPossibleKeys_);
-                break;
-            case CS_KeybindCommand:
-                if (evaluation.key_)
-                    return CommandExecutor::dump(evaluation.key_);
-                break;
-            case CS_KeybindFinished:
-                if (evaluation.key_)
-                    return CommandExecutor::dump(evaluation.key_);
-                break;
-            case CS_Error:
-                return CommandExecutor::getEvaluation().errorMessage_;
-                break;
-        }
-
-        return "";
+        CommandExecutor::parseIfNeeded(command);
+        return CommandExecutor::getEvaluation().hint();
     }
 
     CommandEvaluation CommandExecutor::evaluate(const std::string& command)
     {
-        CommandExecutor::parse(command, true);
-
-        if (CommandExecutor::getEvaluation().tokens_.size() > 0)
-        {
-            std::string lastToken;
-            lastToken = CommandExecutor::getEvaluation().tokens_[CommandExecutor::getEvaluation().tokens_.size() - 1];
-            lastToken = lastToken.substr(0, lastToken.size() - 1);
-            CommandExecutor::getEvaluation().tokens_.pop_back();
-            CommandExecutor::getEvaluation().tokens_.append(SubString(lastToken, " ", "", true, '\0', false, '\0', false, '\0', '\0', false, '\0'));
-        }
-
+        CommandExecutor::parse(command);
         CommandExecutor::getEvaluation().evaluateParams();
         return CommandExecutor::getEvaluation();
     }
 
+    void CommandExecutor::parseIfNeeded(const std::string& command)
+    {
+        if (CommandExecutor::getEvaluation().state_ == CS_Uninitialized)
+        {
+            CommandExecutor::parse(command);
+        }
+        else if (CommandExecutor::getEvaluation().originalCommand_ != command)
+        {
+            if (CommandExecutor::getEvaluation().command_ == command)
+            {
+                CommandExecutor::parse(command);
+                CommandExecutor::getEvaluation().bNewCommand_ = false;
+            }
+            else
+            {
+                CommandExecutor::parse(command);
+            }
+        }
+    }
+
     void CommandExecutor::parse(const std::string& command, bool bInitialize)
     {
-        CommandExecutor::getEvaluation().tokens_.split((command + COMMAND_EXECUTOR_CURSOR), " ", SubString::WhiteSpaces, false, '\\', false, '"', false, '(', ')', false, '\0');
-        CommandExecutor::getEvaluation().processedCommand_ = command;
-
         if (bInitialize)
-            CommandExecutor::initialize(command);
+            CommandExecutor::getEvaluation().initialize(command);
+
+        CommandExecutor::getEvaluation().commandTokens_.split(command, " ", SubString::WhiteSpaces, false, '\\', false, '"', false, '(', ')', false, '\0');
+        CommandExecutor::getEvaluation().command_ = command;
 
         switch (CommandExecutor::getEvaluation().state_)
         {
             case CS_Uninitialized:
+            {
                 // Impossible
                 break;
+            }
             case CS_Empty:
+            {
                 if (CommandExecutor::argumentsGiven() == 0)
                 {
-                    // We want a hint for the first token
-                    // Check if there is already a perfect match
-                    CommandExecutor::getEvaluation().functionclass_ = CommandExecutor::getIdentifierOfPossibleFunctionClass(CommandExecutor::getToken(0));
-                    CommandExecutor::getEvaluation().shortcut_ = CommandExecutor::getExecutorOfPossibleShortcut(CommandExecutor::getToken(0));
-
-                    if ((CommandExecutor::getEvaluation().functionclass_) || (CommandExecutor::getEvaluation().shortcut_))
-                    {
-                        // Yes, there is a class or a shortcut with the searched name
-                        // Add a whitespace and continue parsing
-                        CommandExecutor::getEvaluation().state_ = CS_FunctionClass_Or_Shortcut_Or_Keyword;
-                        CommandExecutor::parse(command + " ", false);
+                    CommandExecutor::createListOfPossibleFunctions("");
+                    CommandExecutor::createListOfPossibleIdentifiers("");
+                    break;
+                }
+                else
+                {
+                    CommandExecutor::getEvaluation().state_ = CS_ShortcutOrIdentifier;
+                    // Move on to next case
+                }
+            }
+            case CS_ShortcutOrIdentifier:
+            {
+                if (CommandExecutor::argumentsGiven() > 1)
+                {
+                    // There's a finished first argument - check if it's a shortcut or a classname
+                    CommandExecutor::getEvaluation().function_ = CommandExecutor::getPossibleCommand(CommandExecutor::getArgument(0));
+                    CommandExecutor::getEvaluation().functionclass_ = CommandExecutor::getPossibleIdentifier(CommandExecutor::getArgument(0));
+
+                    if (CommandExecutor::getEvaluation().function_)
+                    {
+                        // It's a shortcut
+                        CommandExecutor::getEvaluation().state_ = CS_ParamPreparation;
+                        CommandExecutor::getEvaluation().functionclass_ = 0;
+                        // Move on to next case
+                    }
+                    else if (CommandExecutor::getEvaluation().functionclass_)
+                    {
+                        // It's a functionname
+                        CommandExecutor::getEvaluation().state_ = CS_Function;
+                        CommandExecutor::getEvaluation().function_ = 0;
+                        // Move on to next case
+                    }
+                    else
+                    {
+                        // The first argument is bad
+                        CommandExecutor::getEvaluation().state_ = CS_Error;
+                        AddLanguageEntry("commandexecutorunknownfirstargument", "is not a shortcut nor a classname");
+                        CommandExecutor::getEvaluation().errorMessage_ = "Error: " + CommandExecutor::getArgument(0) + " " + GetLocalisation("commandexecutorunknownfirstargument") + ".";
                         return;
                     }
-
-                    // No perfect match: Create the lists of all possible classes and shortcuts and return
-                    CommandExecutor::createListOfPossibleFunctionClasses(CommandExecutor::getToken(0));
-                    CommandExecutor::createListOfPossibleShortcuts(CommandExecutor::getToken(0));
-
-                    // Check if there's only one possiblility
-                    if ((CommandExecutor::getEvaluation().listOfPossibleFunctionClasses_.size() == 1) && (CommandExecutor::getEvaluation().listOfPossibleShortcuts_.size() == 0))
-                    {
-                        // There's only one possible class
+                }
+                else
+                {
+                    // There's no finished first argument - search possible shortcuts or classnames
+                    CommandExecutor::createListOfPossibleFunctions(CommandExecutor::getArgument(0));
+                    CommandExecutor::createListOfPossibleIdentifiers(CommandExecutor::getArgument(0));
+
+                    unsigned int num_functions = CommandExecutor::getEvaluation().listOfPossibleFunctions_.size();
+                    unsigned int num_identifiers = CommandExecutor::getEvaluation().listOfPossibleIdentifiers_.size();
+
+                    if (num_functions == 1 && num_identifiers == 0)
+                    {
+                        // It's a shortcut
+                        std::string functionname = *(*CommandExecutor::getEvaluation().listOfPossibleFunctions_.begin()).first;
+                        CommandExecutor::getEvaluation().function_ = CommandExecutor::getPossibleCommand(functionname);
+                        if (getLowercase(functionname) != getLowercase(CommandExecutor::getArgument(0)))
+                        {
+                            // Unfinished shortcut
+                            CommandExecutor::getEvaluation().bCommandChanged_ = true;
+                        }
+                        CommandExecutor::getEvaluation().state_ = CS_ParamPreparation;
+                        CommandExecutor::getEvaluation().functionclass_ = 0;
+                        CommandExecutor::getEvaluation().command_ = CommandExecutor::getEvaluation().function_->getName();
+                        if (CommandExecutor::getEvaluation().function_->getParamCount() > 0)
+                        {
+                            CommandExecutor::getEvaluation().command_ += " ";
+                            CommandExecutor::getEvaluation().bCommandChanged_ = true;
+                        }
+                        // Move on to next case
+                    }
+                    else if (num_identifiers == 1 && num_functions == 0)
+                    {
+                        // It's a classname
+                        std::string classname = *(*CommandExecutor::getEvaluation().listOfPossibleIdentifiers_.begin()).first;
+                        CommandExecutor::getEvaluation().functionclass_ = CommandExecutor::getPossibleIdentifier(classname);
+                        if (getLowercase(classname) != getLowercase(CommandExecutor::getArgument(0)))
+                        {
+                            // Unfinished classname
+                            CommandExecutor::getEvaluation().bCommandChanged_ = true;
+                        }
                         CommandExecutor::getEvaluation().state_ = CS_Function;
-                        CommandExecutor::getEvaluation().functionclass_ = CommandExecutor::getIdentifierOfPossibleFunctionClass(*(*CommandExecutor::getEvaluation().listOfPossibleFunctionClasses_.begin()).first);
-                        CommandExecutor::parse(*(*CommandExecutor::getEvaluation().listOfPossibleFunctionClasses_.begin()).first + " ", false);
+                        CommandExecutor::getEvaluation().function_ = 0;
+                        CommandExecutor::getEvaluation().command_ = CommandExecutor::getEvaluation().functionclass_->getName() + " ";
+                        // Move on to next case
+                    }
+                    else if (num_identifiers == 0 && num_functions == 0)
+                    {
+                        // No possibilities
+                        CommandExecutor::getEvaluation().state_ = CS_Error;
+                        AddLanguageEntry("commandexecutorunknownfirstargumentstart", "There is no command or classname starting with");
+                        CommandExecutor::getEvaluation().errorMessage_ = "Error: " + GetLocalisation("commandexecutorunknownfirstargumentstart") + " " + CommandExecutor::getArgument(0) + ".";
                         return;
                     }
-                    else if ((CommandExecutor::getEvaluation().listOfPossibleFunctionClasses_.size() == 0) && (CommandExecutor::getEvaluation().listOfPossibleShortcuts_.size() == 1))
-                    {
-                        if ((*(*CommandExecutor::getEvaluation().listOfPossibleShortcuts_.begin()).first != COMMAND_EXECUTOR_KEYWORD_SET_CONFIG_VALUE)
-                         && (*(*CommandExecutor::getEvaluation().listOfPossibleShortcuts_.begin()).first != COMMAND_EXECUTOR_KEYWORD_SET_CONFIG_VALUE_TEMPORARY)
-                         && (*(*CommandExecutor::getEvaluation().listOfPossibleShortcuts_.begin()).first != COMMAND_EXECUTOR_KEYWORD_SET_KEYBIND))
-                        {
-                            // There's only one possible shortcut
-                            CommandExecutor::getEvaluation().state_ = CS_Shortcut_Params;
-                            CommandExecutor::getEvaluation().shortcut_ = CommandExecutor::getExecutorOfPossibleShortcut(*(*CommandExecutor::getEvaluation().listOfPossibleShortcuts_.begin()).first);
-                        }
-                        else if ((*(*CommandExecutor::getEvaluation().listOfPossibleShortcuts_.begin()).first == COMMAND_EXECUTOR_KEYWORD_SET_CONFIG_VALUE)
-                              || (*(*CommandExecutor::getEvaluation().listOfPossibleShortcuts_.begin()).first == COMMAND_EXECUTOR_KEYWORD_SET_CONFIG_VALUE_TEMPORARY))
-                        {
-                            // It's the 'set' or 'tset' keyword
-                            CommandExecutor::getEvaluation().state_ = CS_ConfigValueClass;
-                        }
-                        else if (*(*CommandExecutor::getEvaluation().listOfPossibleShortcuts_.begin()).first != COMMAND_EXECUTOR_KEYWORD_SET_KEYBIND)
-                        {
-                            // It's the 'bind' keyword
-                            CommandExecutor::getEvaluation().state_ = CS_KeybindKey;
-                        }
-
-                        CommandExecutor::parse(*(*CommandExecutor::getEvaluation().listOfPossibleShortcuts_.begin()).first + " ", false);
+                    else
+                    {
+                        // There are several possiblilities
+                        std::list<std::pair<const std::string*, const std::string*> > temp;
+                        temp.insert(temp.end(), CommandExecutor::getEvaluation().listOfPossibleFunctions_.begin(), CommandExecutor::getEvaluation().listOfPossibleFunctions_.end());
+                        temp.insert(temp.end(), CommandExecutor::getEvaluation().listOfPossibleIdentifiers_.begin(), CommandExecutor::getEvaluation().listOfPossibleIdentifiers_.end());
+                        CommandExecutor::getEvaluation().command_ = CommandExecutor::getCommonBegin(temp);
+                        CommandExecutor::getEvaluation().function_ = CommandExecutor::getPossibleCommand(CommandExecutor::getArgument(0));
+                        CommandExecutor::getEvaluation().functionclass_ = CommandExecutor::getPossibleIdentifier(CommandExecutor::getArgument(0));
+                        CommandExecutor::getEvaluation().bCommandChanged_ = true;
                         return;
                     }
-
-                    // It's ambiguous
+                }
+            }
+            case CS_Function:
+            {
+                if (CommandExecutor::getEvaluation().functionclass_)
+                {
+                    // There is a classname - search for the commandname
+                    if (CommandExecutor::argumentsGiven() > 2)
+                    {
+                        // There is a finished second argument - check if it's a commandname
+                        CommandExecutor::getEvaluation().function_ = CommandExecutor::getPossibleCommand(CommandExecutor::getArgument(1), CommandExecutor::getEvaluation().functionclass_);
+
+                        if (CommandExecutor::getEvaluation().function_)
+                        {
+                            // It's a function
+                            CommandExecutor::getEvaluation().state_ = CS_ParamPreparation;
+                            // Move on to next case
+                        }
+                        else
+                        {
+                            // The second argument is bad
+                            CommandExecutor::getEvaluation().state_ = CS_Error;
+                            AddLanguageEntry("commandexecutorunknownsecondargument", "is not a function of");
+                            CommandExecutor::getEvaluation().errorMessage_ = "Error: " + CommandExecutor::getArgument(1) + " " + GetLocalisation("commandexecutorunknownsecondargument") + " " + CommandExecutor::getEvaluation().functionclass_->getName() + ".";
+                            return;
+                        }
+                    }
+                    else
+                    {
+                        // There is no finished second argument - search for possibilities
+                        CommandExecutor::createListOfPossibleFunctions(CommandExecutor::getArgument(1), CommandExecutor::getEvaluation().functionclass_);
+                        unsigned int num_functions = CommandExecutor::getEvaluation().listOfPossibleFunctions_.size();
+
+                        if (num_functions == 1)
+                        {
+                            // It's a function
+                            std::string functionname = *(*CommandExecutor::getEvaluation().listOfPossibleFunctions_.begin()).first;
+                            CommandExecutor::getEvaluation().function_ = CommandExecutor::getPossibleCommand(functionname, CommandExecutor::getEvaluation().functionclass_);
+                            if (getLowercase(functionname) != getLowercase(CommandExecutor::getArgument(1)))
+                            {
+                                // Unfinished function
+                                CommandExecutor::getEvaluation().bCommandChanged_ = true;
+                            }
+                            CommandExecutor::getEvaluation().state_ = CS_ParamPreparation;
+                            CommandExecutor::getEvaluation().command_ = CommandExecutor::getEvaluation().functionclass_->getName() + " " + CommandExecutor::getEvaluation().function_->getName();
+                            if (CommandExecutor::getEvaluation().function_->getParamCount() > 0)
+                            {
+                                CommandExecutor::getEvaluation().command_ += " ";
+                                CommandExecutor::getEvaluation().bCommandChanged_ = true;
+                            }
+                            // Move on to next case
+                        }
+                        else if (num_functions == 0)
+                        {
+                            // No possibilities
+                            CommandExecutor::getEvaluation().state_ = CS_Error;
+                            AddLanguageEntry("commandexecutorunknownsecondargumentstart", "has no function starting with");
+                            CommandExecutor::getEvaluation().errorMessage_ = "Error: " + CommandExecutor::getEvaluation().functionclass_->getName() + " " + GetLocalisation("commandexecutorunknownsecondargumentstart") + " " + CommandExecutor::getArgument(1) + ".";
+                            return;
+                        }
+                        else
+                        {
+                            // There are several possibilities
+                            CommandExecutor::getEvaluation().command_ = CommandExecutor::getEvaluation().functionclass_->getName() + " " + CommandExecutor::getCommonBegin(CommandExecutor::getEvaluation().listOfPossibleFunctions_);
+                            CommandExecutor::getEvaluation().function_ = CommandExecutor::getPossibleCommand(CommandExecutor::getArgument(1), CommandExecutor::getEvaluation().functionclass_);
+                            CommandExecutor::getEvaluation().bCommandChanged_ = true;
+                            return;
+                        }
+                    }
+                }
+                else
+                {
+                    // There is no classname - move on to CS_ParamPreparation
+                }
+            }
+            case CS_ParamPreparation:
+            {
+                if (CommandExecutor::getEvaluation().function_->getParamCount() == 0 || CommandExecutor::enoughArgumentsGiven(CommandExecutor::getEvaluation().function_))
+                {
+                    CommandExecutor::getEvaluation().state_ = CS_Finished;
                     return;
                 }
                 else
                 {
-                    // There is at least one argument: Check if it's a shortcut, a classname or a special keyword
-                    CommandExecutor::getEvaluation().state_ = CS_FunctionClass_Or_Shortcut_Or_Keyword;
-                    CommandExecutor::parse(command, false);
+                    unsigned int argumentNumber = CommandExecutor::argumentsGiven() - 2;
+                    if (CommandExecutor::getEvaluation().functionclass_)
+                        argumentNumber -= 1;
+
+                    CommandExecutor::createListOfPossibleArguments(CommandExecutor::getLastArgument(), CommandExecutor::getEvaluation().function_, argumentNumber);
+                    CommandExecutor::getEvaluation().state_ = CS_Params;
+
+                    if (CommandExecutor::getEvaluation().bCommandChanged_)
+                    {
+                        // Don't do more than one change
+                        return;
+                    }
+                }
+            }
+            case CS_Params:
+            {
+                if (CommandExecutor::getEvaluation().listOfPossibleArguments_.size() == 1)
+                {
+                    // There is exactly one possible argument
+                    CommandExecutor::getEvaluation().argument_ = (*CommandExecutor::getEvaluation().listOfPossibleArguments_.begin()).getString();
+                    CommandExecutor::getEvaluation().possibleArgument_ = (*CommandExecutor::getEvaluation().listOfPossibleArguments_.begin()).getString();
+                    CommandExecutor::getEvaluation().state_ = CS_ParamPreparation;
                     return;
                 }
+                else if (CommandExecutor::getEvaluation().listOfPossibleArguments_.size() == 0)
+                {
+                    // The user tries something new - we let him do
+                    CommandExecutor::getEvaluation().state_ = CS_ParamPreparation;
+                    CommandExecutor::getEvaluation().argument_ = CommandExecutor::getLastArgument();
+                    return;
+                }
+                else
+                {
+                    // There are several possibilities
+                    unsigned int argumentNumber = CommandExecutor::argumentsGiven();
+                    if (argumentNumber > 0)
+                        --argumentNumber;
+                    if (CommandExecutor::getEvaluation().functionclass_ && argumentNumber > 0)
+                        --argumentNumber;
+
+                    CommandExecutor::getEvaluation().argument_ = CommandExecutor::getCommonBegin(CommandExecutor::getEvaluation().listOfPossibleArguments_);
+                    CommandExecutor::getEvaluation().possibleArgument_ = CommandExecutor::getPossibleArgument(CommandExecutor::getLastArgument(), CommandExecutor::getEvaluation().function_, argumentNumber);
+                    CommandExecutor::getEvaluation().state_ = CS_ParamPreparation;
+                    return;
+                }
+            }
+            case CS_Finished:
+            {
+                // Nothing more to do
                 break;
-            case CS_FunctionClass_Or_Shortcut_Or_Keyword:
-                if (CommandExecutor::argumentsGiven() >= 1)
-                {
-                    if ((CommandExecutor::getToken(0) == COMMAND_EXECUTOR_KEYWORD_SET_CONFIG_VALUE) || (CommandExecutor::getToken(0) == COMMAND_EXECUTOR_KEYWORD_SET_CONFIG_VALUE_TEMPORARY))
-                    {
-                        // We want to set a config value
-                        CommandExecutor::getEvaluation().state_ = CS_ConfigValueClass;
-                        CommandExecutor::parse(command, false);
-                        return;
-                    }
-                    else if (CommandExecutor::getToken(0) == COMMAND_EXECUTOR_KEYWORD_SET_KEYBIND)
-                    {
-                        // We want to set a keybinding
-                        CommandExecutor::getEvaluation().state_ = CS_KeybindKey;
-                        CommandExecutor::parse(command, false);
-                        return;
-                    }
-
-                    if (!CommandExecutor::getEvaluation().functionclass_)
-                        CommandExecutor::getEvaluation().functionclass_ = CommandExecutor::getIdentifierOfPossibleFunctionClass(CommandExecutor::getToken(0));
-                    if (!CommandExecutor::getEvaluation().shortcut_)
-                        CommandExecutor::getEvaluation().shortcut_ = CommandExecutor::getExecutorOfPossibleShortcut(CommandExecutor::getToken(0));
-
-                    if ((!CommandExecutor::getEvaluation().functionclass_) && (!CommandExecutor::getEvaluation().shortcut_))
-                    {
-                        // Argument 1 seems to be wrong
-                        AddLanguageEntry("CommandExecutor::NoSuchCommandOrClassName", "No such command or classname");
-                        CommandExecutor::getEvaluation().errorMessage_ = (CommandExecutor::getToken(0) + ": " + GetLocalisation("CommandExecutor::NoSuchCommandOrClassName"));
-                        CommandExecutor::getEvaluation().state_ = CS_Error;
-                        return;
-                    }
-                    else if (CommandExecutor::getEvaluation().shortcut_)
-                    {
-                        // Argument 1 is a shortcut: Return the needed parameter types
-                        CommandExecutor::getEvaluation().state_ = CS_Shortcut_Params;
-                        CommandExecutor::parse(command, false);
-                        return;
-                    }
-                    else
-                    {
-                        // Argument 1 is a classname: Return the possible functions
-                        CommandExecutor::getEvaluation().state_ = CS_Function;
-                        CommandExecutor::parse(command, false);
-                        return;
-                    }
-                }
-                else
-                {
-                    CommandExecutor::getEvaluation().state_ = CS_Error;
-                    return;
-                }
+            }
+            case CS_Error:
+            {
+                // Bad, very bad
                 break;
-            case CS_Shortcut_Params:
-                if (CommandExecutor::getEvaluation().shortcut_)
-                {
-                    // Valid command
-                    // Check if there are enough parameters
-                    if (CommandExecutor::enoughParametersGiven(1, CommandExecutor::getEvaluation().shortcut_))
-                    {
-                        CommandExecutor::getEvaluation().state_ = CS_Shortcut_Finished;
-                        return;
-                    }
-                }
-                else
-                {
-                    // Something is wrong
-                    CommandExecutor::getEvaluation().state_ = CS_Error;
-                    return;
-                }
-                break;
-            case CS_Function:
-                if (CommandExecutor::getEvaluation().functionclass_)
-                {
-                    // We have a valid classname
-                    // Check if there is a second argument
-                    if (CommandExecutor::argumentsGiven() >= 2)
-                    {
-                        // There is a second argument: Check if it's a valid functionname
-                        CommandExecutor::getEvaluation().function_ = CommandExecutor::getExecutorOfPossibleFunction(CommandExecutor::getToken(1), CommandExecutor::getEvaluation().functionclass_);
-                        if (!CommandExecutor::getEvaluation().function_)
-                        {
-                            // Argument 2 seems to be wrong
-                            AddLanguageEntry("CommandExecutor::NoSuchFunctionnameIn", "No such functionname in");
-                            CommandExecutor::getEvaluation().errorMessage_ = (CommandExecutor::getToken(1) + ": " + GetLocalisation("CommandExecutor::NoSuchFunctionnameIn") + " " + CommandExecutor::getEvaluation().functionclass_->getName());
-                            CommandExecutor::getEvaluation().state_ = CS_Error;
-                            return;
-                        }
-                        else
-                        {
-                            // Argument 2 seems to be a valid functionname: Get the parameters
-                            CommandExecutor::getEvaluation().state_ = CS_Function_Params;
-                            CommandExecutor::parse(command, false);
-                            return;
-                        }
-                    }
-                    else
-                    {
-                        // There is no finished second argument
-                        // Check if there's already a perfect match
-                        if (CommandExecutor::getEvaluation().tokens_.size() >= 2)
-                        {
-                            CommandExecutor::getEvaluation().function_ = CommandExecutor::getExecutorOfPossibleFunction(CommandExecutor::getToken(1), CommandExecutor::getEvaluation().functionclass_);
-                            if (CommandExecutor::getEvaluation().function_)
-                            {
-                                // There is a perfect match: Add a whitespace and continue parsing
-                                CommandExecutor::getEvaluation().state_ = CS_Function_Params;
-                                CommandExecutor::parse(command + " ", false);
-                                return;
-                            }
-                        }
-
-                        // No perfect match: Create the list of all possible functions and return
-                        CommandExecutor::createListOfPossibleFunctions(CommandExecutor::getToken(1), CommandExecutor::getEvaluation().functionclass_);
-
-                        // Check if there's only one possiblility
-                        if (CommandExecutor::getEvaluation().listOfPossibleFunctions_.size() == 1)
-                        {
-                            // There's only one possible function
-                            CommandExecutor::getEvaluation().state_ = CS_Function_Params;
-                            CommandExecutor::getEvaluation().function_ = CommandExecutor::getExecutorOfPossibleFunction(*(*CommandExecutor::getEvaluation().listOfPossibleFunctions_.begin()).first, CommandExecutor::getEvaluation().functionclass_);
-                            CommandExecutor::parse(CommandExecutor::getToken(0) + " " + *(*CommandExecutor::getEvaluation().listOfPossibleFunctions_.begin()).first + " ", false);
-                            return;
-                        }
-
-                        // It's ambiguous
-                        return;
-                    }
-                }
-                else
-                {
-                    CommandExecutor::getEvaluation().state_ = CS_Error;
-                    return;
-                }
-                break;
-            case CS_Function_Params:
-                if (CommandExecutor::getEvaluation().functionclass_ && CommandExecutor::getEvaluation().function_)
-                {
-                    // Valid command
-                    // Check if there are enough parameters
-                    if (CommandExecutor::enoughParametersGiven(2, CommandExecutor::getEvaluation().function_))
-                    {
-                        CommandExecutor::getEvaluation().state_ = CS_Function_Finished;
-                        return;
-                    }
-                }
-                else
-                {
-                    // Something is wrong
-                    CommandExecutor::getEvaluation().state_ = CS_Error;
-                    return;
-                }
-                break;
-            case CS_ConfigValueClass:
-                if (((CommandExecutor::getToken(0) == COMMAND_EXECUTOR_KEYWORD_SET_CONFIG_VALUE) || (CommandExecutor::getToken(0) == COMMAND_EXECUTOR_KEYWORD_SET_CONFIG_VALUE_TEMPORARY)))
-                {
-                    // We want to set a config value
-                    // Check if there is a second argument
-                    if (CommandExecutor::argumentsGiven() >= 2)
-                    {
-                        // There is a second argument: Check if it's a valid classname
-                        CommandExecutor::getEvaluation().configvalueclass_ = CommandExecutor::getIdentifierOfPossibleConfigValueClass(CommandExecutor::getToken(1));
-                        if (!CommandExecutor::getEvaluation().configvalueclass_)
-                        {
-                            // Argument 2 seems to be wrong
-                            AddLanguageEntry("CommandExecutor::NoSuchClassWithConfigValues", "No such class with config values");
-                            CommandExecutor::getEvaluation().errorMessage_ = (CommandExecutor::getToken(1) + ": " + GetLocalisation("CommandExecutor::NoSuchClassWithConfigValues"));
-                            CommandExecutor::getEvaluation().state_ = CS_Error;
-                            return;
-                        }
-                        else
-                        {
-                            // Argument 2 seems to be a valid classname: Search for possible config values
-                            CommandExecutor::getEvaluation().state_ = CS_ConfigValue;
-                            CommandExecutor::parse(command, false);
-                            return;
-                        }
-                    }
-                    else
-                    {
-                        // There's no finished second argument
-                        // Check if there's already a perfect match
-                        if (CommandExecutor::getEvaluation().tokens_.size() >= 2)
-                        {
-                            CommandExecutor::getEvaluation().configvalueclass_ = CommandExecutor::getIdentifierOfPossibleConfigValueClass(CommandExecutor::getToken(1));
-                            if (CommandExecutor::getEvaluation().configvalueclass_)
-                            {
-                                // There is a perfect match: Add a whitespace and continue parsing
-                                CommandExecutor::getEvaluation().state_ = CS_ConfigValue;
-                                CommandExecutor::parse(command + " ", false);
-                                return;
-                            }
-                        }
-
-                        // No perfect match: Create the list of all possible classnames and return
-                        CommandExecutor::createListOfPossibleConfigValueClasses(CommandExecutor::getToken(1));
-
-                        // Check if there's only one possiblility
-                        if (CommandExecutor::getEvaluation().listOfPossibleConfigValueClasses_.size() == 1)
-                        {
-                            // There's only one possible classname
-                            CommandExecutor::getEvaluation().state_ = CS_ConfigValue;
-                            CommandExecutor::getEvaluation().configvalueclass_ = CommandExecutor::getIdentifierOfPossibleConfigValueClass(*(*CommandExecutor::getEvaluation().listOfPossibleConfigValueClasses_.begin()).first);
-                            CommandExecutor::parse(CommandExecutor::getToken(0) + " " + *(*CommandExecutor::getEvaluation().listOfPossibleConfigValueClasses_.begin()).first + " ", false);
-                            return;
-                        }
-
-                        // It's ambiguous
-                        return;
-                    }
-                }
-                else
-                {
-                    // Something is wrong
-                    CommandExecutor::getEvaluation().state_ = CS_Error;
-                    return;
-                }
-                break;
-            case CS_ConfigValue:
-                if (((CommandExecutor::getToken(0) == COMMAND_EXECUTOR_KEYWORD_SET_CONFIG_VALUE) || (CommandExecutor::getToken(0) == COMMAND_EXECUTOR_KEYWORD_SET_CONFIG_VALUE_TEMPORARY)) && (CommandExecutor::getEvaluation().configvalueclass_))
-                {
-                    // Check if there is a third argument
-                    if (CommandExecutor::argumentsGiven() >= 3)
-                    {
-                        // There is a third argument: Check if it's a valid config value
-                        CommandExecutor::getEvaluation().configvalue_ = CommandExecutor::getContainerOfPossibleConfigValue(CommandExecutor::getToken(2), CommandExecutor::getEvaluation().configvalueclass_);
-                        if (!CommandExecutor::getEvaluation().configvalue_)
-                        {
-                            // Argument 3 seems to be wrong
-                            AddLanguageEntry("CommandExecutor::NoSuchConfigValueIn", "No such config value in");
-                            CommandExecutor::getEvaluation().errorMessage_ = (CommandExecutor::getToken(2) + ": " + GetLocalisation("CommandExecutor::NoSuchConfigValueIn") + " " + CommandExecutor::getEvaluation().configvalueclass_->getName());
-                            CommandExecutor::getEvaluation().state_ = CS_Error;
-                            return;
-                        }
-                        else
-                        {
-                            // Argument 3 seems to be a valid config value: Get the type
-                            CommandExecutor::getEvaluation().state_ = CS_ConfigValueType;
-                            CommandExecutor::parse(command, false);
-                            return;
-                        }
-                    }
-                    else
-                    {
-                        // There is no finished third argument
-                        // Check if there's already a perfect match
-                        if (CommandExecutor::getEvaluation().tokens_.size() >= 3)
-                        {
-                            CommandExecutor::getEvaluation().configvalue_ = CommandExecutor::getContainerOfPossibleConfigValue(CommandExecutor::getToken(2), CommandExecutor::getEvaluation().configvalueclass_);
-                            if (CommandExecutor::getEvaluation().configvalue_)
-                            {
-                                // There is a perfect match: Add a whitespace and continue parsing
-                                CommandExecutor::getEvaluation().state_ = CS_ConfigValueType;
-                                CommandExecutor::parse(command + " ", false);
-                                return;
-                            }
-                        }
-
-                        // No perfect match: Create the list of all possible config values
-                        CommandExecutor::createListOfPossibleConfigValues(CommandExecutor::getToken(2), CommandExecutor::getEvaluation().configvalueclass_);
-
-                        // Check if there's only one possiblility
-                        if (CommandExecutor::getEvaluation().listOfPossibleConfigValues_.size() == 1)
-                        {
-                            // There's only one possible config value
-                            CommandExecutor::getEvaluation().state_ = CS_ConfigValueType;
-                            CommandExecutor::getEvaluation().configvalue_ = CommandExecutor::getContainerOfPossibleConfigValue(*(*CommandExecutor::getEvaluation().listOfPossibleConfigValues_.begin()).first, CommandExecutor::getEvaluation().configvalueclass_);
-                            CommandExecutor::parse(CommandExecutor::getToken(0) + " " + CommandExecutor::getToken(1) + " " + *(*CommandExecutor::getEvaluation().listOfPossibleConfigValues_.begin()).first + " ", false);
-                            return;
-                        }
-
-                        // It's ambiguous
-                        return;
-                    }
-                }
-                else
-                {
-                    // Something is wrong
-                    CommandExecutor::getEvaluation().state_ = CS_Error;
-                    return;
-                }
-                break;
-            case CS_ConfigValueType:
-                if (((CommandExecutor::getToken(0) == COMMAND_EXECUTOR_KEYWORD_SET_CONFIG_VALUE) || (CommandExecutor::getToken(0) == COMMAND_EXECUTOR_KEYWORD_SET_CONFIG_VALUE_TEMPORARY)) && CommandExecutor::getEvaluation().configvalueclass_ && CommandExecutor::getEvaluation().configvalue_)
-                {
-                    // Valid command
-                    // Check if there are enough parameters
-                    if ((CommandExecutor::getEvaluation().tokens_.size() >= 4) && (CommandExecutor::getEvaluation().tokens_[3] != COMMAND_EXECUTOR_CURSOR))
-                    {
-                        CommandExecutor::getEvaluation().state_ = CS_ConfigValueFinished;
-                        return;
-                    }
-                }
-                else
-                {
-                    // Something is wrong
-                    CommandExecutor::getEvaluation().state_ = CS_Error;
-                    return;
-                }
-                break;
-            case CS_KeybindKey:
-                if ((CommandExecutor::getToken(0) == COMMAND_EXECUTOR_KEYWORD_SET_KEYBIND))
-                {
-                    // todo
-                }
-                else
-                {
-                    // Something is wrong
-                    CommandExecutor::getEvaluation().state_ = CS_Error;
-                    return;
-                }
-                break;
-            case CS_KeybindCommand:
-                if ((CommandExecutor::getToken(0) == COMMAND_EXECUTOR_KEYWORD_SET_KEYBIND) && (false)) // todo
-                {
-                    // Valid command
-                    // Check if there are enough parameters
-                    if (CommandExecutor::getEvaluation().tokens_.size() >= 3)
-                    {
-                        CommandExecutor::getEvaluation().state_ = CS_KeybindFinished;
-                        return;
-                    }
-
-                }
-                else
-                {
-                    // Something is wrong
-                    CommandExecutor::getEvaluation().state_ = CS_Error;
-                    return;
-                }
-                break;
-            case CS_Shortcut_Finished:
-                // Nothing to do
-                break;
-            case CS_Function_Finished:
-                // Nothing to do
-                break;
-            case CS_ConfigValueFinished:
-                // Nothing to do
-                break;
-            case CS_KeybindFinished:
-                // Nothing to do
-                break;
-            case CS_Error:
-                // This is bad
-                break;
-        }
-    }
-
-    void CommandExecutor::initialize(const std::string& command)
-    {
-        CommandExecutor::getEvaluation().processedCommand_ = command;
-        CommandExecutor::getEvaluation().additionalParameter_ = "";
-
-        CommandExecutor::getEvaluation().bEvaluatedParams_ = false;
-        CommandExecutor::getEvaluation().evaluatedExecutor_ = 0;
-
-        CommandExecutor::getEvaluation().listOfPossibleFunctionClasses_.clear();
-        CommandExecutor::getEvaluation().listOfPossibleShortcuts_.clear();
+            }
+        }
+    }
+
+    unsigned int CommandExecutor::argumentsFinished()
+    {
+        unsigned int argumentsGiven = CommandExecutor::argumentsGiven();
+        if (argumentsGiven > 0)
+            return argumentsGiven - 1;
+        else
+            return 0;
+    }
+
+    unsigned int CommandExecutor::argumentsGiven()
+    {
+        if (CommandExecutor::getEvaluation().command_.size() > 0 && CommandExecutor::getEvaluation().command_[CommandExecutor::getEvaluation().command_.size() - 1] == ' ')
+            return CommandExecutor::getEvaluation().commandTokens_.size() + 1;
+        else
+            return CommandExecutor::getEvaluation().commandTokens_.size();
+    }
+
+    bool CommandExecutor::enoughArgumentsGiven(ConsoleCommand* command)
+    {
+        if (CommandExecutor::getEvaluation().functionclass_)
+            return (CommandExecutor::argumentsGiven() > (2 + command->getParamCount()));
+        else
+            return (CommandExecutor::argumentsGiven() > (1 + command->getParamCount()));
+    }
+
+    std::string CommandExecutor::getArgument(unsigned int index)
+    {
+        if (index < (CommandExecutor::getEvaluation().commandTokens_.size()))
+            return CommandExecutor::getEvaluation().commandTokens_[index];
+        else
+            return "";
+    }
+
+    std::string CommandExecutor::getLastArgument()
+    {
+        return CommandExecutor::getArgument(CommandExecutor::argumentsGiven() - 1);
+    }
+
+    void CommandExecutor::createListOfPossibleIdentifiers(const std::string& fragment)
+    {
+        CommandExecutor::getEvaluation().listOfPossibleIdentifiers_.clear();
+        std::string lowercase = getLowercase(fragment);
+        for (std::map<std::string, Identifier*>::const_iterator it = Identifier::getLowercaseIdentifierMapBegin(); it != Identifier::getLowercaseIdentifierMapEnd(); ++it)
+            if ((*it).second->hasConsoleCommands())
+                if ((*it).first.find(lowercase) == 0 || fragment == "")
+                    CommandExecutor::getEvaluation().listOfPossibleIdentifiers_.push_back(std::pair<const std::string*, const std::string*>(&(*it).first, &(*it).second->getName()));
+    }
+
+    void CommandExecutor::createListOfPossibleFunctions(const std::string& fragment, Identifier* identifier)
+    {
         CommandExecutor::getEvaluation().listOfPossibleFunctions_.clear();
-        CommandExecutor::getEvaluation().listOfPossibleConfigValueClasses_.clear();
-        CommandExecutor::getEvaluation().listOfPossibleConfigValues_.clear();
-        CommandExecutor::getEvaluation().listOfPossibleKeys_.clear();
-
-        CommandExecutor::getEvaluation().functionclass_ = 0;
-        CommandExecutor::getEvaluation().configvalueclass_ = 0;
-        CommandExecutor::getEvaluation().shortcut_ = 0;
-        CommandExecutor::getEvaluation().function_ = 0;
-        CommandExecutor::getEvaluation().configvalue_ = 0;
-        CommandExecutor::getEvaluation().key_ = 0;
-
-        CommandExecutor::getEvaluation().errorMessage_ = "";
-        CommandExecutor::getEvaluation().state_ = CS_Empty;
-    }
-
-    bool CommandExecutor::argumentsGiven(unsigned int num)
-    {
-        // Because we added a cursor we have +1 arguments
-        // There are num arguments given if there are at least num arguments + one cursor
-        return (CommandExecutor::getEvaluation().tokens_.size() >= (num + 1));
-    }
-
-    unsigned int CommandExecutor::argumentsGiven()
-    {
-        // Because we added a cursor we have +1 arguments
-        if (CommandExecutor::getEvaluation().tokens_.size() >= 1)
-            return (CommandExecutor::getEvaluation().tokens_.size() - 1);
-        else
-            return 0;
-    }
-
-    std::string CommandExecutor::getToken(unsigned int index)
-    {
-        if ((index >= 0) && (index < (CommandExecutor::getEvaluation().tokens_.size() - 1)))
-            return CommandExecutor::getEvaluation().tokens_[index];
-        else if (index == (CommandExecutor::getEvaluation().tokens_.size() - 1))
-            return CommandExecutor::getEvaluation().tokens_[index].substr(0, CommandExecutor::getEvaluation().tokens_[index].size() - 1);
-        else
-            return "";
-    }
-
-    bool CommandExecutor::enoughParametersGiven(unsigned int head, Executor* executor)
-    {
-        unsigned int neededParams = head + executor->getParamCount();
-        /*
-        for (unsigned int i = executor->getParamCount() - 1; i >= 0; i--)
-        {
-            if (executor->defaultValueSet(i))
-                neededParams--;
+        std::string lowercase = getLowercase(fragment);
+        if (!identifier)
+        {
+            for (std::map<std::string, ConsoleCommand*>::const_iterator it = CommandExecutor::getLowercaseConsoleCommandShortcutMapBegin(); it != CommandExecutor::getLowercaseConsoleCommandShortcutMapEnd(); ++it)
+                if ((*it).first.find(lowercase) == 0 || fragment == "")
+                    CommandExecutor::getEvaluation().listOfPossibleFunctions_.push_back(std::pair<const std::string*, const std::string*>(&(*it).first, &(*it).second->getName()));
+        }
+        else
+        {
+            for (std::map<std::string, ConsoleCommand*>::const_iterator it = identifier->getLowercaseConsoleCommandMapBegin(); it != identifier->getLowercaseConsoleCommandMapEnd(); ++it)
+                if ((*it).first.find(lowercase) == 0 || fragment == "")
+                    CommandExecutor::getEvaluation().listOfPossibleFunctions_.push_back(std::pair<const std::string*, const std::string*>(&(*it).first, &(*it).second->getName()));
+        }
+    }
+
+    void CommandExecutor::createListOfPossibleArguments(const std::string& fragment, ConsoleCommand* command, unsigned int param)
+    {
+        CommandExecutor::createArgumentCompletionList(command, param);
+
+        CommandExecutor::getEvaluation().listOfPossibleArguments_.clear();
+        std::string lowercase = getLowercase(fragment);
+        for (ArgumentCompletionList::const_iterator it = command->getArgumentCompletionListBegin(); it != command->getArgumentCompletionListEnd(); ++it)
+        {
+            if ((*it).lowercaseComparison())
+            {
+                if ((*it).getComparable().find(lowercase) == 0 || fragment == "")
+                    CommandExecutor::getEvaluation().listOfPossibleArguments_.push_back(*it);
+            }
             else
-                break;
-        }
-        */
-        return ((CommandExecutor::getEvaluation().tokens_.size() >= neededParams) && (CommandExecutor::getEvaluation().tokens_[neededParams - 1] != COMMAND_EXECUTOR_CURSOR));
-    }
-
-    void CommandExecutor::createListOfPossibleFunctionClasses(const std::string& fragment)
-    {
-        for (std::map<std::string, Identifier*>::const_iterator it = Identifier::getLowercaseIdentifierMapBegin(); it != Identifier::getLowercaseIdentifierMapEnd(); ++it)
-        {
-            if ((*it).second->hasConsoleCommands())
-            {
-                if ((*it).first.find(getLowercase(fragment)) == 0 || fragment == "")
-                {
-                    CommandExecutor::getEvaluation().listOfPossibleFunctionClasses_.push_back(std::pair<const std::string*, const std::string*>(&(*it).first, &(*it).second->getName()));
-                }
-            }
-        }
-
-        CommandExecutor::getEvaluation().listOfPossibleFunctionClasses_.sort(CommandExecutor::compareStringsInList);
-    }
-
-    void CommandExecutor::createListOfPossibleShortcuts(const std::string& fragment)
-    {
-        for (std::map<std::string, ExecutorStatic*>::const_iterator it = CommandExecutor::getLowercaseConsoleCommandShortcutMapBegin(); it != CommandExecutor::getLowercaseConsoleCommandShortcutMapEnd(); ++it)
-        {
-            if ((*it).first.find(getLowercase(fragment)) == 0 || fragment == "")
-            {
-                CommandExecutor::getEvaluation().listOfPossibleShortcuts_.push_back(std::pair<const std::string*, const std::string*>(&(*it).first, &(*it).second->getName()));
-            }
-        }
-
-        CommandExecutor::getEvaluation().listOfPossibleShortcuts_.sort(CommandExecutor::compareStringsInList);
-    }
-
-    void CommandExecutor::createListOfPossibleFunctions(const std::string& fragment, Identifier* identifier)
-    {
-        for (std::map<std::string, ExecutorStatic*>::const_iterator it = identifier->getLowercaseConsoleCommandMapBegin(); it != identifier->getLowercaseConsoleCommandMapEnd(); ++it)
-        {
-            if ((*it).first.find(getLowercase(fragment)) == 0 || fragment == "")
-            {
-                CommandExecutor::getEvaluation().listOfPossibleFunctions_.push_back(std::pair<const std::string*, const std::string*>(&(*it).first, &(*it).second->getName()));
-            }
-        }
-
-        CommandExecutor::getEvaluation().listOfPossibleFunctions_.sort(CommandExecutor::compareStringsInList);
-    }
-
-    void CommandExecutor::createListOfPossibleConfigValueClasses(const std::string& fragment)
-    {
-        for (std::map<std::string, Identifier*>::const_iterator it = Identifier::getLowercaseIdentifierMapBegin(); it != Identifier::getLowercaseIdentifierMapEnd(); ++it)
-        {
-            if ((*it).second->hasConfigValues())
-            {
-                if ((*it).first.find(getLowercase(fragment)) == 0 || fragment == "")
-                {
-                    CommandExecutor::getEvaluation().listOfPossibleConfigValueClasses_.push_back(std::pair<const std::string*, const std::string*>(&(*it).first, &(*it).second->getName()));
-                }
-            }
-        }
-
-        CommandExecutor::getEvaluation().listOfPossibleConfigValueClasses_.sort(CommandExecutor::compareStringsInList);
-    }
-
-    void CommandExecutor::createListOfPossibleConfigValues(const std::string& fragment, Identifier* identifier)
-    {
-        for (std::map<std::string, ConfigValueContainer*>::const_iterator it = identifier->getLowercaseConfigValueMapBegin(); it != identifier->getLowercaseConfigValueMapEnd(); ++it)
-        {
-            if ((*it).first.find(getLowercase(fragment)) == 0 || fragment == "")
-            {
-                CommandExecutor::getEvaluation().listOfPossibleConfigValues_.push_back(std::pair<const std::string*, const std::string*>(&(*it).first, &(*it).second->getName()));
-            }
-        }
-
-        CommandExecutor::getEvaluation().listOfPossibleConfigValues_.sort(CommandExecutor::compareStringsInList);
-    }
-
-    void CommandExecutor::createListOfPossibleKeys(const std::string& fragment)
-    {
-        // todo
-
-        CommandExecutor::getEvaluation().listOfPossibleKeys_.sort(CommandExecutor::compareStringsInList);
-    }
-
-    bool CommandExecutor::compareStringsInList(const std::pair<const std::string*, const std::string*>& first, const std::pair<const std::string*, const std::string*>& second)
-    {
-        return ((*first.first) < (*second.first));
-    }
-
-    Identifier* CommandExecutor::getIdentifierOfPossibleFunctionClass(const std::string& name)
-    {
-        std::map<std::string, Identifier*>::const_iterator it = Identifier::getLowercaseIdentifierMap().find(getLowercase(name));
+            {
+                if ((*it).getComparable().find(fragment) == 0 || fragment == "")
+                    CommandExecutor::getEvaluation().listOfPossibleArguments_.push_back(*it);
+            }
+        }
+    }
+
+    Identifier* CommandExecutor::getPossibleIdentifier(const std::string& name)
+    {
+        std::string lowercase = getLowercase(name);
+        std::map<std::string, Identifier*>::const_iterator it = Identifier::getLowercaseIdentifierMap().find(lowercase);
         if ((it != Identifier::getLowercaseIdentifierMapEnd()) && (*it).second->hasConsoleCommands())
             return (*it).second;
@@ -1252,92 +508,60 @@
     }
 
-    ExecutorStatic* CommandExecutor::getExecutorOfPossibleShortcut(const std::string& name)
-    {
-        std::map<std::string, ExecutorStatic*>::const_iterator it = CommandExecutor::getLowercaseConsoleCommandShortcutMap().find(getLowercase(name));
-        if (it != CommandExecutor::getLowercaseConsoleCommandShortcutMapEnd())
-            return (*it).second;
-
+    ConsoleCommand* CommandExecutor::getPossibleCommand(const std::string& name, Identifier* identifier)
+    {
+        std::string lowercase = getLowercase(name);
+        if (!identifier)
+        {
+            std::map<std::string, ConsoleCommand*>::const_iterator it = CommandExecutor::getLowercaseConsoleCommandShortcutMap().find(lowercase);
+            if (it != CommandExecutor::getLowercaseConsoleCommandShortcutMapEnd())
+                return (*it).second;
+        }
+        else
+        {
+            std::map<std::string, ConsoleCommand*>::const_iterator it = identifier->getLowercaseConsoleCommandMap().find(lowercase);
+            if (it != identifier->getLowercaseConsoleCommandMapEnd())
+                return (*it).second;
+        }
         return 0;
     }
 
-    ExecutorStatic* CommandExecutor::getExecutorOfPossibleFunction(const std::string& name, Identifier* identifier)
-    {
-        std::map<std::string, ExecutorStatic*>::const_iterator it = identifier->getLowercaseConsoleCommandMap().find(getLowercase(name));
-        if (it != identifier->getLowercaseConsoleCommandMapEnd())
-            return (*it).second;
-
-        return 0;
-    }
-
-    Identifier* CommandExecutor::getIdentifierOfPossibleConfigValueClass(const std::string& name)
-    {
-        std::map<std::string, Identifier*>::const_iterator it = Identifier::getLowercaseIdentifierMap().find(getLowercase(name));
-        if ((it != Identifier::getLowercaseIdentifierMapEnd()) && (*it).second->hasConfigValues())
-            return (*it).second;
-
-        return 0;
-    }
-
-    ConfigValueContainer* CommandExecutor::getContainerOfPossibleConfigValue(const std::string& name, Identifier* identifier)
-    {
-        std::map<std::string, ConfigValueContainer*>::const_iterator it = identifier->getLowercaseConfigValueMap().find(getLowercase(name));
-        if (it != identifier->getLowercaseConfigValueMapEnd())
-        {
-            return (*it).second;
-        }
-
-        return 0;
-    }
-
-    ConfigValueContainer* CommandExecutor::getContainerOfPossibleKey(const std::string& name)
-    {
-        // todo
-
-        return 0;
-    }
-
-    std::string CommandExecutor::dump(const std::list<std::pair<const std::string*, const std::string*> >& list)
-    {
-        std::string output = "";
-        for (std::list<std::pair<const std::string*, const std::string*> >::const_iterator it = list.begin(); it != list.end(); ++it)
-        {
-            if (it != list.begin())
-                output += " ";
-
-            output += *(*it).second;
-        }
-        return output;
-    }
-
-    std::string CommandExecutor::dump(const ExecutorStatic* executor)
-    {
-        std::string output = "";
-        for (unsigned int i = 0; i < executor->getParamCount(); i++)
-        {
-            if (i != 0)
-                output += " ";
-
-            if (executor->defaultValueSet(i))
-                output += "[";
+    std::string CommandExecutor::getPossibleArgument(const std::string& name, ConsoleCommand* command, unsigned int param)
+    {
+        CommandExecutor::createArgumentCompletionList(command, param);
+
+        std::string lowercase = getLowercase(name);
+        for (ArgumentCompletionList::const_iterator it = command->getArgumentCompletionListBegin(); it != command->getArgumentCompletionListEnd(); ++it)
+        {
+            if ((*it).lowercaseComparison())
+            {
+                if ((*it).getComparable() == lowercase)
+                    return (*it).getString();
+            }
             else
-                output += "{";
-
-            output += executor->getTypenameParam(i);
-
-            if (executor->defaultValueSet(i))
-                output += "=" + executor->getDefaultValue(i).toString() + "]";
-            else
-                output += "}";
-        }
-        return output;
-    }
-
-    std::string CommandExecutor::dump(const ConfigValueContainer* container)
-    {
-        AddLanguageEntry("CommandExecutor::oldvalue", "old value");
-        if (!container->isVector())
-            return ("{" + container->getTypename() + "} (" + GetLocalisation("CommandExecutor::oldvalue") + ": " + container->toString() + ")");
-        else
-            return ("(vector<" + container->getTypename() + ">) (size: " + getConvertedValue<unsigned int, std::string>(container->getVectorSize()) + ")");
+            {
+                if ((*it).getComparable() == name)
+                    return (*it).getString();
+            }
+        }
+
+        return "";
+    }
+
+    void CommandExecutor::createArgumentCompletionList(ConsoleCommand* command, unsigned int param)
+    {
+        std::string params[5];
+
+        unsigned int index = 0;
+        unsigned int lowestIndex = 1 + (CommandExecutor::getEvaluation().functionclass_ != 0);
+
+        for (unsigned int i = CommandExecutor::argumentsGiven() - 1; i >= lowestIndex; --i)
+        {
+            params[index] = CommandExecutor::getArgument(i);
+            ++index;
+            if (index >= 5)
+                break;
+        }
+
+        command->createArgumentCompletionList(param, params[0], params[1], params[2], params[3], params[4]);
     }
 
@@ -1382,3 +606,45 @@
         }
     }
+
+    std::string CommandExecutor::getCommonBegin(const ArgumentCompletionList& list)
+    {
+        if (list.size() == 0)
+        {
+            return "";
+        }
+        else if (list.size() == 1)
+        {
+            return ((*list.begin()).getComparable() + " ");
+        }
+        else
+        {
+            std::string output = "";
+            for (unsigned int i = 0; true; i++)
+            {
+                char temp = 0;
+                for (ArgumentCompletionList::const_iterator it = list.begin(); it != list.end(); ++it)
+                {
+                    std::string argument = (*it).getComparable();
+                    if (argument.size() > i)
+                    {
+                        if (it == list.begin())
+                        {
+                            temp = argument[i];
+                        }
+                        else
+                        {
+                            if (temp != argument[i])
+                                return output;
+                        }
+                    }
+                    else
+                    {
+                        return output;
+                    }
+                }
+                output += temp;
+            }
+            return output;
+        }
+    }
 }
Index: code/trunk/src/core/CommandExecutor.h
===================================================================
--- code/trunk/src/core/CommandExecutor.h	(revision 1407)
+++ code/trunk/src/core/CommandExecutor.h	(revision 1502)
@@ -32,133 +32,37 @@
 #include "CorePrereqs.h"
 
-#include <string>
 #include <map>
-#include <list>
 
-#include "util/SubString.h"
-#include "util/MultiTypeMath.h"
-
-#define COMMAND_EXECUTOR_CURSOR "$"
+#include "CommandEvaluation.h"
 
 namespace orxonox
 {
-    enum CommandState
-    {
-        CS_Uninitialized,
-        CS_Empty,
-        CS_FunctionClass_Or_Shortcut_Or_Keyword,
-        CS_Shortcut_Params,
-        CS_Shortcut_Finished,
-        CS_Function,
-        CS_Function_Params,
-        CS_Function_Finished,
-        CS_ConfigValueClass,
-        CS_ConfigValue,
-        CS_ConfigValueType,
-        CS_ConfigValueFinished,
-        CS_KeybindKey,
-        CS_KeybindCommand,
-        CS_KeybindFinished,
-        CS_Error
-    };
-
-    void exec(const std::string& filename);
-    std::string echo(const std::string& text);
-
-    void write(const std::string& filename, const std::string& text);
-    void append(const std::string& filename, const std::string& text);
-    std::string read(const std::string& filename);
-
-    ///////////////////////
-    // CommandEvaluation //
-    ///////////////////////
-    class _CoreExport CommandEvaluation
-    {
-        friend class CommandExecutor;
-
-        public:
-            CommandEvaluation();
-
-            KeybindMode::Enum getKeybindMode();
-            bool isValid() const;
-
-            inline void setAdditionalParameter(const std::string& param)
-                { this->additionalParameter_ = param; this->bEvaluatedParams_ = false; }
-            inline std::string getAdditionalParameter() const
-                { return (this->additionalParameter_ != "") ? (" " + this->additionalParameter_) : ""; }
-            inline ExecutorStatic* getEvaluatedExecutor() { return evaluatedExecutor_; }
-            inline std::string getCommandString() { return this->processedCommand_; }
-
-            void setEvaluatedParameter(unsigned int index, MultiTypeMath param);
-            MultiTypeMath getEvaluatedParameter(unsigned int index) const;
-
-            void evaluateParams();
-
-            bool hasReturnvalue() const;
-            MultiTypeMath getReturnvalue() const;
-
-        private:
-            std::string processedCommand_;
-            SubString tokens_;
-            std::string additionalParameter_;
-
-            std::list<std::pair<const std::string*, const std::string*> > listOfPossibleFunctionClasses_;
-            std::list<std::pair<const std::string*, const std::string*> > listOfPossibleShortcuts_;
-            std::list<std::pair<const std::string*, const std::string*> > listOfPossibleFunctions_;
-            std::list<std::pair<const std::string*, const std::string*> > listOfPossibleConfigValueClasses_;
-            std::list<std::pair<const std::string*, const std::string*> > listOfPossibleConfigValues_;
-            std::list<std::pair<const std::string*, const std::string*> > listOfPossibleKeys_;
-
-            Identifier* functionclass_;
-            Identifier* configvalueclass_;
-            ExecutorStatic* shortcut_;
-            ExecutorStatic* function_;
-            ConfigValueContainer* configvalue_;
-            ConfigValueContainer* key_;
-
-            std::string errorMessage_;
-            CommandState state_;
-
-            bool bEvaluatedParams_;
-            MultiTypeMath param_[5];
-            ExecutorStatic* evaluatedExecutor_;
-    };
-
-    /////////////////////
-    // CommandExecutor //
-    /////////////////////
     class _CoreExport CommandExecutor
     {
         public:
             static bool execute(const std::string& command, bool useTcl = true);
-            static bool execute(const CommandEvaluation& evaluation);
-
             static std::string complete(const std::string& command);
-            static std::string complete(const CommandEvaluation& evaluation);
-
             static std::string hint(const std::string& command);
-            static std::string hint(const CommandEvaluation& evaluation);
 
             static CommandEvaluation evaluate(const std::string& command);
-
             static const CommandEvaluation& getLastEvaluation();
 
-            static Executor& addConsoleCommandShortcut(ExecutorStatic* executor);
-            static ExecutorStatic* getConsoleCommandShortcut(const std::string& name);
-            static ExecutorStatic* getLowercaseConsoleCommandShortcut(const std::string& name);
+            static ConsoleCommand& addConsoleCommandShortcut(ConsoleCommand* command);
+            static ConsoleCommand* getConsoleCommandShortcut(const std::string& name);
+            static ConsoleCommand* getLowercaseConsoleCommandShortcut(const std::string& name);
 
             /** @brief Returns the map that stores all console commands. @return The const_iterator */
-            static inline const std::map<std::string, ExecutorStatic*>& getConsoleCommandShortcutMap() { return CommandExecutor::getInstance().consoleCommandShortcuts_; }
+            static inline const std::map<std::string, ConsoleCommand*>& getConsoleCommandShortcutMap() { return CommandExecutor::getInstance().consoleCommandShortcuts_; }
             /** @brief Returns a const_iterator to the beginning of the map that stores all console commands. @return The const_iterator */
-            static inline std::map<std::string, ExecutorStatic*>::const_iterator getConsoleCommandShortcutMapBegin() { return CommandExecutor::getInstance().consoleCommandShortcuts_.begin(); }
+            static inline std::map<std::string, ConsoleCommand*>::const_iterator getConsoleCommandShortcutMapBegin() { return CommandExecutor::getInstance().consoleCommandShortcuts_.begin(); }
             /** @brief Returns a const_iterator to the end of the map that stores all console commands. @return The const_iterator */
-            static inline std::map<std::string, ExecutorStatic*>::const_iterator getConsoleCommandShortcutMapEnd() { return CommandExecutor::getInstance().consoleCommandShortcuts_.end(); }
+            static inline std::map<std::string, ConsoleCommand*>::const_iterator getConsoleCommandShortcutMapEnd() { return CommandExecutor::getInstance().consoleCommandShortcuts_.end(); }
 
             /** @brief Returns the map that stores all console commands with their names in lowercase. @return The const_iterator */
-            static inline const std::map<std::string, ExecutorStatic*>& getLowercaseConsoleCommandShortcutMap() { return CommandExecutor::getInstance().consoleCommandShortcuts_LC_; }
+            static inline const std::map<std::string, ConsoleCommand*>& getLowercaseConsoleCommandShortcutMap() { return CommandExecutor::getInstance().consoleCommandShortcuts_LC_; }
             /** @brief Returns a const_iterator to the beginning of the map that stores all console commands with their names in lowercase. @return The const_iterator */
-            static inline std::map<std::string, ExecutorStatic*>::const_iterator getLowercaseConsoleCommandShortcutMapBegin() { return CommandExecutor::getInstance().consoleCommandShortcuts_LC_.begin(); }
+            static inline std::map<std::string, ConsoleCommand*>::const_iterator getLowercaseConsoleCommandShortcutMapBegin() { return CommandExecutor::getInstance().consoleCommandShortcuts_LC_.begin(); }
             /** @brief Returns a const_iterator to the end of the map that stores all console commands with their names in lowercase. @return The const_iterator */
-            static inline std::map<std::string, ExecutorStatic*>::const_iterator getLowercaseConsoleCommandShortcutMapEnd() { return CommandExecutor::getInstance().consoleCommandShortcuts_LC_.end(); }
+            static inline std::map<std::string, ConsoleCommand*>::const_iterator getLowercaseConsoleCommandShortcutMapEnd() { return CommandExecutor::getInstance().consoleCommandShortcuts_LC_.end(); }
 
         private:
@@ -170,40 +74,28 @@
             static CommandEvaluation& getEvaluation();
 
+            static void parseIfNeeded(const std::string& command);
             static void parse(const std::string& command, bool bInitialize = true);
-            static void initialize(const std::string& command);
 
-            static bool argumentsGiven(unsigned int num);
+            static unsigned int argumentsFinished();
             static unsigned int argumentsGiven();
+            static bool enoughArgumentsGiven(ConsoleCommand* command);
+            static std::string getArgument(unsigned int index);
+            static std::string getLastArgument();
 
-            static std::string getToken(unsigned int index);
+            static void createListOfPossibleIdentifiers(const std::string& fragment);
+            static void createListOfPossibleFunctions(const std::string& fragment, Identifier* identifier = 0);
+            static void createListOfPossibleArguments(const std::string& fragment, ConsoleCommand* command, unsigned int param);
 
-            static bool enoughParametersGiven(unsigned int head, Executor* executor);
+            static Identifier* getPossibleIdentifier(const std::string& name);
+            static ConsoleCommand* getPossibleCommand(const std::string& name, Identifier* identifier = 0);
+            static std::string getPossibleArgument(const std::string& name, ConsoleCommand* command, unsigned int param);
 
-            static void createListOfPossibleShortcuts(const std::string& fragment);
-            static void createListOfPossibleFunctionClasses(const std::string& fragment);
-            static void createListOfPossibleFunctions(const std::string& fragment, Identifier* identifier);
-            static void createListOfPossibleConfigValueClasses(const std::string& fragment);
-            static void createListOfPossibleConfigValues(const std::string& fragment, Identifier* identifier);
-            static void createListOfPossibleKeys(const std::string& fragment);
-
-            static bool compareStringsInList(const std::pair<const std::string*, const std::string*>& first, const std::pair<const std::string*, const std::string*>& second);
-
-            static std::string dump(const std::list<std::pair<const std::string*, const std::string*> >& list);
-            static std::string dump(const ExecutorStatic* executor);
-            static std::string dump(const ConfigValueContainer* container);
-
+            static void createArgumentCompletionList(ConsoleCommand* command, unsigned int param);
             static std::string getCommonBegin(const std::list<std::pair<const std::string*, const std::string*> >& list);
-
-            static Identifier* getIdentifierOfPossibleFunctionClass(const std::string& name);
-            static ExecutorStatic* getExecutorOfPossibleShortcut(const std::string& name);
-            static ExecutorStatic* getExecutorOfPossibleFunction(const std::string& name, Identifier* identifier);
-            static Identifier* getIdentifierOfPossibleConfigValueClass(const std::string& name);
-            static ConfigValueContainer* getContainerOfPossibleConfigValue(const std::string& name, Identifier* identifier);
-            static ConfigValueContainer* getContainerOfPossibleKey(const std::string& name);
+            static std::string getCommonBegin(const ArgumentCompletionList& list);
 
             CommandEvaluation evaluation_;
-
-            std::map<std::string, ExecutorStatic*> consoleCommandShortcuts_;
-            std::map<std::string, ExecutorStatic*> consoleCommandShortcuts_LC_;
+            std::map<std::string, ConsoleCommand*> consoleCommandShortcuts_;
+            std::map<std::string, ConsoleCommand*> consoleCommandShortcuts_LC_;
     };
 }
Index: code/trunk/src/core/ConfigFileManager.cc
===================================================================
--- code/trunk/src/core/ConfigFileManager.cc	(revision 1407)
+++ code/trunk/src/core/ConfigFileManager.cc	(revision 1502)
@@ -38,8 +38,34 @@
 namespace orxonox
 {
-    ConsoleCommandShortcutExtern(reloadConfig, AccessLevel::None);
-    ConsoleCommandShortcutExtern(cleanConfig, AccessLevel::None);
-    ConsoleCommandShortcutExtern(loadSettings, AccessLevel::None);
-    ConsoleCommandShortcutExtern(loadKeybindings, AccessLevel::None);
+    SetConsoleCommandShortcutExtern(config).setArgumentCompleter(0, autocompletion::configvalueclasses()).setArgumentCompleter(1, autocompletion::configvalues()).setArgumentCompleter(2, autocompletion::configvalue());
+    SetConsoleCommandShortcutExtern(tconfig).setArgumentCompleter(0, autocompletion::configvalueclasses()).setArgumentCompleter(1, autocompletion::configvalues()).setArgumentCompleter(2, autocompletion::configvalue());
+    SetConsoleCommandShortcutExtern(reloadConfig);
+    SetConsoleCommandShortcutExtern(cleanConfig);
+    SetConsoleCommandShortcutExtern(loadSettings).setArgumentCompleter(0, autocompletion::files());
+    SetConsoleCommandShortcutExtern(loadKeybindings).setArgumentCompleter(0, autocompletion::files());
+
+    bool config(const std::string& classname, const std::string& varname, const std::string& value)
+    {
+        std::map<std::string, Identifier*>::const_iterator identifier = Identifier::getLowercaseIdentifierMap().find(getLowercase(classname));
+        if (identifier != Identifier::getLowercaseIdentifierMapEnd())
+        {
+            std::map<std::string, ConfigValueContainer*>::const_iterator variable = (*identifier).second->getLowercaseConfigValueMap().find(getLowercase(varname));
+            if (variable != (*identifier).second->getLowercaseConfigValueMapEnd())
+                return (*variable).second->set(value);
+        }
+        return false;
+    }
+
+    bool tconfig(const std::string& classname, const std::string& varname, const std::string& value)
+    {
+        std::map<std::string, Identifier*>::const_iterator identifier = Identifier::getLowercaseIdentifierMap().find(getLowercase(classname));
+        if (identifier != Identifier::getLowercaseIdentifierMapEnd())
+        {
+            std::map<std::string, ConfigValueContainer*>::const_iterator variable = (*identifier).second->getLowercaseConfigValueMap().find(getLowercase(varname));
+            if (variable != (*identifier).second->getLowercaseConfigValueMapEnd())
+                return (*variable).second->tset(value);
+        }
+        return false;
+    }
 
     void reloadConfig()
@@ -336,4 +362,12 @@
 
         COUT(4) << "Saved config file \"" << this->filename_ << "\"." << std::endl;
+    }
+
+    void ConfigFile::save(const std::string& filename)
+    {
+        std::string temp = this->filename_;
+        this->filename_ = filename;
+        this->save();
+        this->filename_ = temp;
     }
 
@@ -473,4 +507,9 @@
     }
 
+    void ConfigFileManager::save(ConfigFileType type, const std::string& filename)
+    {
+        this->getFile(type)->save(filename);
+    }
+
     void ConfigFileManager::clean(ConfigFileType type, bool bCleanComments)
     {
Index: code/trunk/src/core/ConfigFileManager.h
===================================================================
--- code/trunk/src/core/ConfigFileManager.h	(revision 1407)
+++ code/trunk/src/core/ConfigFileManager.h	(revision 1502)
@@ -50,4 +50,6 @@
 
 
+    bool config(const std::string& classname, const std::string& varname, const std::string& value);
+    bool tconfig(const std::string& classname, const std::string& varname, const std::string& value);
     void reloadConfig();
     void saveConfig();
@@ -222,4 +224,5 @@
             void load(bool bCreateIfNotExisting = true);
             void save() const;
+            void save(const std::string& filename);
             void clean(bool bCleanComments = false);
 
@@ -265,4 +268,5 @@
             void load(ConfigFileType type, bool bCreateIfNotExisting = true);
             void save(ConfigFileType type);
+            void save(ConfigFileType type, const std::string& filename);
             void clean(ConfigFileType type, bool bCleanComments = false);
 
Index: code/trunk/src/core/ConfigValueContainer.cc
===================================================================
--- code/trunk/src/core/ConfigValueContainer.cc	(revision 1407)
+++ code/trunk/src/core/ConfigValueContainer.cc	(revision 1502)
@@ -87,13 +87,128 @@
 
         if (defvalue.size() > 0)
-            this->value_ = defvalue[0];
-
-        for (unsigned int i = 0; i < defvalue.size(); i++)
-            ConfigFileManager::getSingleton()->getValue(this->type_, this->sectionname_, this->varname_, i, defvalue[i].toString(), this->value_.isA(MT_string));
-
-        for (unsigned int i = 0; i < defvalue.size(); i++)
-            this->defvalueStringVector_.push_back(defvalue[i].toString());
-
-        this->update();
+        {
+                this->value_ = defvalue[0];
+
+            for (unsigned int i = 0; i < defvalue.size(); i++)
+            {
+                ConfigFileManager::getSingleton()->getValue(this->type_, this->sectionname_, this->varname_, i, defvalue[i].toString(), this->value_.isA(MT_string));
+                this->defvalueStringVector_.push_back(defvalue[i].toString());
+            }
+
+            this->update();
+        }
+    }
+
+    /**
+        @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 MultiTypeMath& input)
+    {
+        if (this->bIsVector_)
+        {
+            return this->callFunctionWithIndex(&ConfigValueContainer::set, input.toString());
+        }
+        else
+        {
+            if (this->tset(input))
+            {
+                ConfigFileManager::getSingleton()->setValue(this->type_, this->sectionname_, this->varname_, input.toString(), this->value_.isA(MT_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 MultiTypeMath& input)
+    {
+        if (this->bIsVector_)
+        {
+            if (this->tset(index, input))
+            {
+                ConfigFileManager::getSingleton()->setValue(this->type_, this->sectionname_, this->varname_, index, input.toString(), this->value_.isA(MT_string));
+                return true;
+            }
+        }
+        else
+        {
+            COUT(1) << "Error: Config-value '" << this->varname_ << "' in " << this->sectionname_ << " is not a vector." << std::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 MultiTypeMath& input)
+    {
+        if (this->bIsVector_)
+        {
+            return this->callFunctionWithIndex(&ConfigValueContainer::tset, input.toString());
+        }
+        else
+        {
+            MultiTypeMath temp = this->value_;
+            if (temp.assimilate(input))
+            {
+                this->value_ = temp;
+                if (this->identifier_)
+                    this->identifier_->updateConfigValues();
+
+                return true;
+            }
+        }
+        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 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 MultiTypeMath& input)
+    {
+        if (this->bIsVector_)
+        {
+            if (index > MAX_VECTOR_INDEX)
+            {
+                COUT(1) << "Error: Index " << index << " is too large." << std::endl;
+                return false;
+            }
+
+            if (index >= this->valueVector_.size())
+            {
+                for (unsigned int i = this->valueVector_.size(); i <= index; i++)
+                {
+                    this->valueVector_.push_back(MultiTypeMath());
+                }
+            }
+
+            MultiTypeMath temp = this->value_;
+            if (temp.assimilate(input))
+            {
+                this->valueVector_[index] = temp;
+
+                if (this->identifier_)
+                    this->identifier_->updateConfigValues();
+
+                return true;
+            }
+        }
+        else
+        {
+            COUT(1) << "Error: Config-value '" << this->varname_ << "' in " << this->sectionname_ << " is not a vector." << std::endl;
+        }
+        return false;
     }
 
@@ -103,5 +218,5 @@
         @return True if the new entry was successfully added
     */
-    bool ConfigValueContainer::add(const std::string& input)
+    bool ConfigValueContainer::add(const MultiTypeMath& input)
     {
         if (this->bIsVector_)
@@ -123,4 +238,5 @@
             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++)
@@ -131,96 +247,4 @@
             }
             COUT(1) << "Error: Invalid vector-index." << std::endl;
-        }
-
-        COUT(1) << "Error: Config-value '" << this->varname_ << "' in " << this->sectionname_ << " is not a vector." << std::endl;
-        return false;
-    }
-
-    /**
-        @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 std::string& input)
-    {
-        if (this->bIsVector_)
-        {
-            SubString token(input, " ", "", true, '"', false, '(', ')', false, '\0');
-            int index = -1;
-            bool success = false;
-
-            if (token.size() > 0)
-                success = ConvertValue(&index, token[0]);
-
-            if (!success || index < 0 || index > MAX_VECTOR_INDEX)
-            {
-                if (!success)
-                {
-                    COUT(1) << "Error: Config-value '" << this->varname_ << "' in " << this->sectionname_ << " is a vector." << std::endl;
-                }
-                else
-                {
-                    COUT(1) << "Error: Invalid vector-index." << std::endl;
-                }
-                return false;
-            }
-
-            if (token.size() >= 2)
-                return this->set(index, token.subSet(1).join());
-            else
-                return this->set(index, "");
-        }
-
-        bool success = this->tset(input);
-        ConfigFileManager::getSingleton()->setValue(this->type_, this->sectionname_, this->varname_, input, this->value_.isA(MT_string));
-        return success;
-    }
-
-    /**
-        @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 std::string& input)
-    {
-        if (this->bIsVector_)
-        {
-            bool success = this->tset(index, input);
-            ConfigFileManager::getSingleton()->setValue(this->type_, this->sectionname_, this->varname_, index, input, this->value_.isA(MT_string));
-            return success;
-        }
-
-        COUT(1) << "Error: Config-value '" << this->varname_ << "' in " << this->sectionname_ << " is not a vector." << std::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
-        @return True if the new value was successfully assigned
-    */
-    bool ConfigValueContainer::tset(const std::string& input)
-    {
-        bool success = this->parse(input);
-        if (this->identifier_)
-            this->identifier_->updateConfigValues();
-        return success;
-    }
-
-    /**
-        @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 std::string& input)
-    {
-        if (this->bIsVector_)
-        {
-            bool success = this->parse(index, input);
-            if (this->identifier_)
-                this->identifier_->updateConfigValues();
-            return success;
         }
 
@@ -259,121 +283,50 @@
             for (unsigned int i = 0; i < ConfigFileManager::getSingleton()->getVectorSize(this->type_, this->sectionname_, this->varname_); i++)
             {
-                this->value_.fromString(ConfigFileManager::getSingleton()->getValue(this->type_, this->sectionname_, this->varname_, i, this->defvalueStringVector_[i], this->value_.isA(MT_string)));
-                this->valueVector_.push_back(this->value_);
-            }
-        }
-    }
-
-    /**
-        @brief Parses a given std::string into a value of the type of the associated variable and assigns it.
-        @param input The string to convert
-        @return True if the string was successfully parsed
-    */
-    bool ConfigValueContainer::parse(const std::string& input)
-    {
-        if (this->bIsVector_)
-        {
-            SubString token(input, " ", "", true, '"', false, '(', ')', false, '\0');
-            int index = -1;
-            bool success = false;
-
-            if (token.size() > 0)
-                success = ConvertValue(&index, token[0]);
-
-            if (!success || index < 0 || index > MAX_VECTOR_INDEX)
-            {
-                if (!success)
+                if (i < this->defvalueStringVector_.size())
                 {
-                    COUT(1) << "Error: Config-value '" << this->varname_ << "' in " << this->sectionname_ << " is a vector." << std::endl;
+                    this->value_.fromString(ConfigFileManager::getSingleton()->getValue(this->type_, this->sectionname_, this->varname_, i, this->defvalueStringVector_[i], this->value_.isA(MT_string)));
                 }
                 else
                 {
-                    COUT(1) << "Error: Invalid vector-index." << std::endl;
+                    this->value_.fromString(ConfigFileManager::getSingleton()->getValue(this->type_, this->sectionname_, this->varname_, i, MultiTypeMath(), this->value_.isA(MT_string)));
                 }
-                return false;
-            }
-
-            if (token.size() >= 2)
-                return this->parse(index, token.subSet(1).join());
+
+                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 MultiTypeMath&), const std::string& input)
+    {
+        SubString token(input, " ", SubString::WhiteSpaces, true, '\\', false, '"', false, '(', ')', false, '\0');
+        int index = -1;
+        bool success = false;
+
+        if (token.size() > 0)
+            success = ConvertValue(&index, token[0]);
+
+        if (!success || index < 0 || index > MAX_VECTOR_INDEX)
+        {
+            if (!success)
+            {
+                COUT(1) << "Error: Config-value '" << this->varname_ << "' in " << this->sectionname_ << " is a vector." << std::endl;
+            }
             else
-                return this->parse(index, "");
-        }
-
-        MultiTypeMath temp = this->value_;
-        if (temp.fromString(input))
-        {
-            this->value_ = temp;
-            return true;
-        }
-        return false;
-    }
-
-    /**
-        @brief Parses a given std::string into a value of the type of the associated variable and assigns it.
-        @param index The index in the vector
-        @param input The string to convert
-        @return True if the string was successfully parsed
-    */
-    bool ConfigValueContainer::parse(unsigned int index, const std::string& input)
-    {
-        if (this->bIsVector_)
-        {
-            if (index >= this->valueVector_.size())
-            {
-                for (unsigned int i = this->valueVector_.size(); i <= index; i++)
-                {
-                    this->valueVector_.push_back(MultiTypeMath());
-                    ConfigFileManager::getSingleton()->setValue(this->type_, this->sectionname_, this->varname_, i, this->valueVector_[i], this->value_.isA(MT_string));
-                }
-            }
-
-            MultiTypeMath temp = this->value_;
-            if (temp.fromString(input))
-            {
-                this->valueVector_[index] = temp;
-                return true;
+            {
+                COUT(1) << "Error: Invalid vector-index." << std::endl;
             }
             return false;
         }
 
-        COUT(1) << "Error: Config-value '" << this->varname_ << "' in " << this->sectionname_ << " is not a vector." << std::endl;
-        return false;
-    }
-
-    /**
-        @brief Parses a given std::string into a value of the type of the associated variable and assigns it.
-        @param input The string to convert
-        @param defvalue The default value to assign if the parsing fails
-        @return True if the string was successfully parsed
-    */
-    bool ConfigValueContainer::parse(const std::string& input, const MultiTypeMath& defvalue)
-    {
-        if (this->parse(input))
-            return true;
-
-        this->value_ = defvalue;
-        return false;
-    }
-
-    /**
-        @brief Parses a given std::string into a value of the type of the associated variable and assigns it.
-        @param index The index in the vector
-        @param input The string to convert
-        @param defvalue The default value to assign if the parsing fails
-        @return True if the string was successfully parsed
-    */
-    bool ConfigValueContainer::parse(unsigned int index, const std::string& input, const MultiTypeMath& defvalue)
-    {
-        if (this->bIsVector_)
-        {
-            if (this->parse(index, input))
-                return true;
-
-            this->valueVector_[index] = defvalue;
-            return false;
-        }
-
-        COUT(1) << "Error: Config-value '" << this->varname_ << "' in " << this->sectionname_ << " is not a vector." << std::endl;
-        return false;
+        if (token.size() >= 2)
+            return (this->*function)(index, token.subSet(1).join());
+        else
+            return (this->*function)(index, "");
     }
 
Index: code/trunk/src/core/ConfigValueContainer.h
===================================================================
--- code/trunk/src/core/ConfigValueContainer.h	(revision 1407)
+++ code/trunk/src/core/ConfigValueContainer.h	(revision 1502)
@@ -90,4 +90,11 @@
             }
 
+            template <typename T>
+            inline void setVectorType(const std::vector<T>& value)
+            {
+                this->value_ = T();
+                this->update();
+            }
+
             inline const std::string& getName() const
                 { return this->varname_; }
@@ -100,8 +107,12 @@
             const std::string& getDescription() const;
 
-            bool add(const std::string& input);
+            bool set(const MultiTypeMath& input);
+            bool tset(const MultiTypeMath& input);
+
+            bool set(unsigned int index, const MultiTypeMath& input);
+            bool tset(unsigned int index, const MultiTypeMath& input);
+            bool add(const MultiTypeMath& input);
             bool remove(unsigned int index);
-            bool set(const std::string& input);
-            bool tset(const std::string& input);
+
             bool reset();
             void update();
@@ -115,11 +126,5 @@
 
         private:
-            bool parse(const std::string& input);
-            bool parse(const std::string& input, const MultiTypeMath& defvalue);
-
-            bool set(unsigned int index, const std::string& input);
-            bool tset(unsigned int index, const std::string& input);
-            bool parse(unsigned int index, const std::string& input);
-            bool parse(unsigned int index, const std::string& input, const MultiTypeMath& defvalue);
+            bool callFunctionWithIndex(bool (ConfigValueContainer::* function) (unsigned int, const MultiTypeMath&), const std::string& input);
 
             bool                       bIsVector_;                  //!< True if the container contains a std::vector
Index: code/trunk/src/core/ConfigValueIncludes.h
===================================================================
--- code/trunk/src/core/ConfigValueIncludes.h	(revision 1407)
+++ code/trunk/src/core/ConfigValueIncludes.h	(revision 1502)
@@ -57,4 +57,19 @@
 
 /**
+    @brief Assigns the value, defined in the config-file, to the variable (or the default-value, if there is no entry in the file).
+    @param classname name in which the config value should be stored
+    @param varname The name of the variable
+    @param defvalue The default-value of the variable
+*/
+#define SetConfigValueGeneric(classname, varname, defvalue) \
+    orxonox::ConfigValueContainer* container##varname = ClassManager<classname>::getIdentifier()->getConfigValueContainer(#varname); \
+    if (!container##varname) \
+    { \
+        container##varname = new orxonox::ConfigValueContainer(CFT_Settings, ClassManager<classname>::getIdentifier(), #varname, varname = defvalue); \
+        ClassManager<classname>::getIdentifier()->addConfigValueContainer(#varname, container##varname); \
+    } \
+    container##varname->getValue(&varname)
+
+/**
     @brief Assigns the vector-values, defined in the config-file, to the vector (or the default-value, if there are no entries in the file).
     @param varname The name of the std::vector
@@ -69,4 +84,5 @@
             temp.push_back(MultiTypeMath(defvalue[i])); \
         container##varname = new orxonox::ConfigValueContainer(CFT_Settings, this->getIdentifier(), #varname, temp); \
+        container##varname->setVectorType(varname); \
         this->getIdentifier()->addConfigValueContainer(#varname, container##varname); \
     } \
@@ -106,16 +122,3 @@
     }
 
-/**
-    @brief Assigns the command, defined in the keybind-file, to the key-variable (or an empty string, if there is no entry in the file).
-    @param varname The name of the key-variable
-*/
-#define SetKeybind(keyname) \
-    orxonox::ConfigValueContainer* container##keyname = this->getIdentifier()->getConfigValueContainer(#keyname); \
-    if (!container##keyname) \
-    { \
-        container##keyname = new orxonox::ConfigValueContainer(CFT_Keybindings, this->getIdentifier(), #keyname, keyname = ""); \
-        this->getIdentifier()->addConfigValueContainer(#keyname, container##keyname); \
-    } \
-    container##keyname->getValue(&varname)
-
 #endif /* _ConfigValueIncludes_H__ */
Index: code/trunk/src/core/ConsoleCommand.cc
===================================================================
--- code/trunk/src/core/ConsoleCommand.cc	(revision 1502)
+++ code/trunk/src/core/ConsoleCommand.cc	(revision 1502)
@@ -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:
+ *      ...
+ *
+ */
+
+#include "ConsoleCommand.h"
+
+namespace orxonox
+{
+    ConsoleCommand::ConsoleCommand(FunctorStatic* functor, const std::string& name) : ExecutorStatic(functor, name)
+    {
+        this->accessLevel_ = AccessLevel::None;
+        this->argumentCompleter_[0] = 0;
+        this->argumentCompleter_[1] = 0;
+        this->argumentCompleter_[2] = 0;
+        this->argumentCompleter_[3] = 0;
+        this->argumentCompleter_[4] = 0;
+
+        this->keybindMode_ = KeybindMode::OnPress;
+        this->axisParamIndex_ = -1;
+        this->bAxisRelative_ = false;
+    }
+
+    ConsoleCommand& ConsoleCommand::setArgumentCompleter(unsigned int param, ArgumentCompleter* completer)
+    {
+        if (param < 5)
+            this->argumentCompleter_[param] = completer;
+        else
+        {
+            COUT(2) << "Warning: Couldn't add autocompletion-function for param " << param << ": index out of bound." << std::endl;
+        }
+        return (*this);
+    }
+
+    ArgumentCompleter* ConsoleCommand::getArgumentCompleter(unsigned int param) const
+    {
+        if (param < 5)
+            return this->argumentCompleter_[param];
+        else
+            return 0;
+    }
+
+    void ConsoleCommand::createArgumentCompletionList(unsigned int param, const std::string& param1, const std::string& param2, const std::string& param3, const std::string& param4, const std::string& param5)
+    {
+        if (param < 5 && this->argumentCompleter_[param])
+            this->argumentList_ = (*this->argumentCompleter_[param])(param1, param2, param3, param4, param5);
+        else
+            this->argumentList_.clear();
+    }
+}
Index: code/trunk/src/core/ConsoleCommand.h
===================================================================
--- code/trunk/src/core/ConsoleCommand.h	(revision 1407)
+++ code/trunk/src/core/ConsoleCommand.h	(revision 1502)
@@ -34,25 +34,110 @@
 #include "Executor.h"
 #include "ClassManager.h"
-#include "Identifier.h"
 #include "CommandExecutor.h"
+#include "ArgumentCompletionFunctions.h"
 
 
+#define SetConsoleCommand(classname, function,  bCreateShortcut) \
+    SetConsoleCommandGeneric(classname##function##consolecommand__, classname, orxonox::createConsoleCommand(orxonox::createFunctor(&classname::function), #function), bCreateShortcut)
 
-#define ConsoleCommand(classname, function, accesslevel, bCreateShortcut) \
-    ConsoleCommandGeneric(classname##function##consolecommand__, classname, orxonox::createExecutor(orxonox::createFunctor(&classname::function), #function, accesslevel), bCreateShortcut)
-
-#define ConsoleCommandGeneric(fakevariable, classname, executor, bCreateShortcut) \
-    Executor& fakevariable = ClassManager<classname>::getIdentifier()->addConsoleCommand((ExecutorStatic*)executor, bCreateShortcut)
+#define SetConsoleCommandGeneric(fakevariable, classname, command, bCreateShortcut) \
+    ConsoleCommand& fakevariable = ClassManager<classname>::getIdentifier()->addConsoleCommand(command, bCreateShortcut)
 
 
-#define ConsoleCommandShortcut(classname, function, accesslevel) \
-    ConsoleCommandShortcutGeneric(function##consolecommand__, orxonox::createExecutor(orxonox::createFunctor(&classname::function), #function, accesslevel))
+#define SetConsoleCommandShortcut(classname, function) \
+    SetConsoleCommandShortcutGeneric(function##consolecommand__, orxonox::createConsoleCommand(orxonox::createFunctor(&classname::function), #function))
 
-#define ConsoleCommandShortcutExtern(function, accesslevel) \
-    ConsoleCommandShortcutGeneric(function##consolecommand__, orxonox::createExecutor(orxonox::createFunctor(&function), #function, accesslevel))
+#define SetConsoleCommandShortcutExtern(function) \
+    SetConsoleCommandShortcutGeneric(function##consolecommand__, orxonox::createConsoleCommand(orxonox::createFunctor(&function), #function))
 
-#define ConsoleCommandShortcutGeneric(fakevariable, executor) \
-    Executor& fakevariable = CommandExecutor::addConsoleCommandShortcut((ExecutorStatic*)executor)
+#define SetConsoleCommandShortcutGeneric(fakevariable, command) \
+    ConsoleCommand& fakevariable = CommandExecutor::addConsoleCommandShortcut(command)
 
 
+namespace orxonox
+{
+    namespace AccessLevel
+    {
+        enum Level
+        {
+            None,
+            User,
+            Admin,
+            Offline,
+            Debug,
+            Disabled
+        };
+    }
+
+    class _CoreExport ConsoleCommand : public ExecutorStatic
+    {
+        public:
+            ConsoleCommand(FunctorStatic* functor, const std::string& name = "");
+
+            inline ConsoleCommand& setDescription(const std::string& description)
+                { this->ExecutorStatic::setDescription(description); return (*this); }
+            inline ConsoleCommand& setDescriptionParam(int param, const std::string& description)
+                { this->ExecutorStatic::setDescriptionParam(param, description); return (*this); }
+            inline ConsoleCommand& setDescriptionReturnvalue(const std::string& description)
+                { this->ExecutorStatic::setDescriptionReturnvalue(description); return (*this); }
+            inline ConsoleCommand& setDefaultValues(const MultiTypeMath& param1)
+                { this->ExecutorStatic::setDefaultValues(param1); return (*this); }
+            inline ConsoleCommand& setDefaultValues(const MultiTypeMath& param1, const MultiTypeMath& param2)
+                { this->ExecutorStatic::setDefaultValues(param1, param2); return (*this); }
+            inline ConsoleCommand& setDefaultValues(const MultiTypeMath& param1, const MultiTypeMath& param2, const MultiTypeMath& param3)
+                { this->ExecutorStatic::setDefaultValues(param1, param2, param3); return (*this); }
+            inline ConsoleCommand& setDefaultValues(const MultiTypeMath& param1, const MultiTypeMath& param2, const MultiTypeMath& param3, const MultiTypeMath& param4)
+                { this->ExecutorStatic::setDefaultValues(param1, param2, param3, param4); return (*this); }
+            inline ConsoleCommand& setDefaultValues(const MultiTypeMath& param1, const MultiTypeMath& param2, const MultiTypeMath& param3, const MultiTypeMath& param4, const MultiTypeMath& param5)
+                { this->ExecutorStatic::setDefaultValues(param1, param2, param3, param4, param5); return (*this); }
+            inline ConsoleCommand& setDefaultValue(unsigned int index, const MultiTypeMath& param)
+                { this->ExecutorStatic::setDefaultValue(index, param); return (*this); }
+
+            inline ConsoleCommand& setAccessLevel(AccessLevel::Level level)
+                { this->accessLevel_ = level; return (*this); }
+            inline AccessLevel::Level getAccessLevel() const
+                { return this->accessLevel_; }
+
+            ConsoleCommand& setArgumentCompleter(unsigned int param, ArgumentCompleter* completer);
+            ArgumentCompleter* getArgumentCompleter(unsigned int param) const;
+
+            void createArgumentCompletionList(unsigned int param, const std::string& param1 = "", const std::string& param2 = "", const std::string& param3 = "", const std::string& param4 = "", const std::string& param5 = "");
+            const ArgumentCompletionList& getArgumentCompletionList() const
+                { return this->argumentList_; }
+            ArgumentCompletionList::const_iterator getArgumentCompletionListBegin() const
+                { return this->argumentList_.begin(); }
+            ArgumentCompletionList::const_iterator getArgumentCompletionListEnd() const
+                { return this->argumentList_.end(); }
+
+            inline ConsoleCommand& setKeybindMode(KeybindMode::Enum mode)
+                { this->keybindMode_ = mode; return *this; }
+            inline KeybindMode::Enum getKeybindMode() const
+                { return this->keybindMode_; }
+
+            inline ConsoleCommand& setAxisParamIndex(int index)
+                { this->axisParamIndex_ = index; return *this; }
+            inline int getAxisParamIndex() const
+                { return this->axisParamIndex_; }
+
+            inline ConsoleCommand& setIsAxisRelative(bool val)
+                { this->bAxisRelative_ = val; return *this; }
+            inline int getIsAxisRelative() const
+                { return this->bAxisRelative_; }
+
+        private:
+            AccessLevel::Level accessLevel_;
+            ArgumentCompleter* argumentCompleter_[5];
+            ArgumentCompletionList argumentList_;
+
+            KeybindMode::Enum keybindMode_;
+            int axisParamIndex_;
+            bool bAxisRelative_;
+    };
+
+    inline ConsoleCommand* createConsoleCommand(FunctorStatic* functor, const std::string& name = "")
+    {
+        return new ConsoleCommand(functor, name);
+    }
+}
+
 #endif /* _ConsoleCommand_H__ */
Index: code/trunk/src/core/ConsoleCommandCompilation.cc
===================================================================
--- code/trunk/src/core/ConsoleCommandCompilation.cc	(revision 1502)
+++ code/trunk/src/core/ConsoleCommandCompilation.cc	(revision 1502)
@@ -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 "ConsoleCommandCompilation.h"
+#include "ConsoleCommand.h"
+#include "Debug.h"
+#include "util/ExprParser.h"
+
+namespace orxonox
+{
+    SetConsoleCommandShortcutExtern(source).setArgumentCompleter(0, autocompletion::files());
+    SetConsoleCommandShortcutExtern(echo);
+    SetConsoleCommandShortcutExtern(puts);
+
+    SetConsoleCommandShortcutExtern(read).setArgumentCompleter(0, autocompletion::files());
+    SetConsoleCommandShortcutExtern(append).setArgumentCompleter(0, autocompletion::files());
+    SetConsoleCommandShortcutExtern(write).setArgumentCompleter(0, autocompletion::files());
+
+    SetConsoleCommandShortcutExtern(calculate);
+
+    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())
+        {
+            COUT(1) << "Error: Recurring source command in \"" << filename << "\". Stopped execution." << std::endl;
+            return;
+        }
+
+        // Open the file
+        std::ifstream file;
+        file.open(filename.c_str(), std::fstream::in);
+
+        if (!file.is_open())
+        {
+            COUT(1) << "Error: Couldn't open file \"" << filename << "\"." << std::endl;
+            return;
+        }
+
+        executingFiles.insert(filename);
+
+        // Iterate through the file and put the lines into the CommandExecutor
+        char line[1024];
+        while (file.good() && !file.eof())
+        {
+            file.getline(line, 1024);
+            CommandExecutor::execute(line);
+        }
+
+        executingFiles.erase(filename);
+        file.close();
+    }
+
+    std::string echo(const std::string& text)
+    {
+        std::cout << text << std::endl;
+        return text;
+    }
+
+    void puts(bool newline, const std::string& text)
+    {
+        if (newline)
+        {
+            COUT(0) << text << std::endl;
+        }
+        else
+        {
+            COUT(0) << text;
+        }
+    }
+
+    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())
+        {
+            COUT(1) << "Error: Couldn't write to file \"" << filename << "\"." << std::endl;
+            return;
+        }
+
+        file << text << std::endl;
+        file.close();
+    }
+
+    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())
+        {
+            COUT(1) << "Error: Couldn't append to file \"" << filename << "\"." << std::endl;
+            return;
+        }
+
+        file << text << std::endl;
+        file.close();
+    }
+
+    std::string read(const std::string& filename)
+    {
+        std::ifstream file;
+        file.open(filename.c_str(), std::fstream::in);
+
+        if (!file.is_open())
+        {
+            COUT(1) << "Error: Couldn't read from file \"" << filename << "\"." << std::endl;
+            return "";
+        }
+
+        std::string output = "";
+        char line[1024];
+        while (file.good() && !file.eof())
+        {
+            file.getline(line, 1024);
+            output += line;
+            output += "\n";
+        }
+
+        file.close();
+
+        return output;
+    }
+
+    float calculate(const std::string& calculation)
+    {
+        ExprParser expr(calculation);
+        if (expr.getSuccess())
+        {
+            if (expr.getResult() == 42.0)
+            {
+                COUT(3) << "Greetings from the restaurant at the end of the universe." << std::endl;
+            }
+            if (expr.getRemains() != "")
+            {
+                COUT(2) << "Warning: Expression could not be parsed to the end! Remains: '" << expr.getRemains() << "'" << std::endl;
+            }
+            return expr.getResult();
+        }
+        else
+        {
+            COUT(1) << "Error: Cannot calculate expression: Parse error." << std::endl;
+            return 0;
+        }
+    }
+}
Index: code/trunk/src/core/ConsoleCommandCompilation.h
===================================================================
--- code/trunk/src/core/ConsoleCommandCompilation.h	(revision 1502)
+++ code/trunk/src/core/ConsoleCommandCompilation.h	(revision 1502)
@@ -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 _ConsoleCommandCompilation_H__
+#define _ConsoleCommandCompilation_H__
+
+#include "CorePrereqs.h"
+
+#include <string>
+
+namespace orxonox
+{
+    _CoreExport void source(const std::string& filename);
+    _CoreExport std::string echo(const std::string& text);
+    _CoreExport void puts(bool newline, const std::string& test);
+
+    _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/trunk/src/core/CorePrereqs.h
===================================================================
--- code/trunk/src/core/CorePrereqs.h	(revision 1407)
+++ code/trunk/src/core/CorePrereqs.h	(revision 1502)
@@ -35,5 +35,5 @@
 #define _CorePrereqs_H__
 
-#include "OrxonoxPlatform.h"
+#include "util/OrxonoxPlatform.h"
 
 #include <string>
@@ -66,6 +66,4 @@
 namespace orxonox
 {
-#ifndef _XMLPort_Mode__
-#define _XMLPort_Mode__
   namespace XMLPort
   {
@@ -76,5 +74,4 @@
     };
   }
-#endif
 
   namespace KeybindMode
@@ -91,4 +88,6 @@
   typedef std::string LanguageEntryLabel;
 
+  class ArgumentCompleter;
+  class ArgumentCompletionListElement;
   class BaseFactory;
   class BaseMetaObjectListElement;
@@ -112,4 +111,5 @@
   class ConfigFileSection;
   class ConfigValueContainer;
+  class ConsoleCommand;
   class CoreSettings;
   class Error;
@@ -125,4 +125,5 @@
   class Identifier;
   class IdentifierDistributor;
+  class IRC;
   template <class T>
   class Iterator;
@@ -141,9 +142,14 @@
   class ObjectListElement;
   class OrxonoxClass;
+  class OutputBuffer;
+  class OutputBufferListener;
   class OutputHandler;
   class Shell;
+  class ShellListener;
   template <class T>
   class SubclassIdentifier;
   class TclBind;
+  struct TclInterpreterBundle;
+  class TclThreadManager;
   class Tickable;
   template <class T, class O>
@@ -156,4 +162,6 @@
   // input
   //class GUIInputHandler;
+  class Calibrator;
+  class CalibratorCallback;
   class InputBuffer;
   class InputBufferListener;
@@ -161,5 +169,5 @@
   class JoyStickHandler;
   class KeyBinder;
-  class KeyHandler;
+  class KeyDetector;
   class MouseHandler;
 
Index: code/trunk/src/core/CoreSettings.cc
===================================================================
--- code/trunk/src/core/CoreSettings.cc	(revision 1407)
+++ code/trunk/src/core/CoreSettings.cc	(revision 1502)
@@ -117,5 +117,7 @@
 
     /**
-        @brief Static function that holds the singleton.
+        @brief Returns the softDebugLevel for the given device (returns a default-value if the class ist right about to be created).
+        @param device The device
+        @return The softDebugLevel
     */
     int CoreSettings::getSoftDebugLevel(OutputHandler::OutputDevice device)
@@ -136,4 +138,24 @@
         return 2;
     }
+
+     /**
+        @brief Sets the softDebugLevel for the given device. Please use this only temporary and restore the value afterwards, as it overrides the configured value.
+        @param device The device
+        @param level The level
+    */
+     void CoreSettings::setSoftDebugLevel(OutputHandler::OutputDevice device, int level)
+     {
+        if (!CoreSettings::isCreatingCoreSettings())
+        {
+            if (device == OutputHandler::LD_All)
+                CoreSettings::getInstance().softDebugLevel_ = level;
+            else if (device == OutputHandler::LD_Console)
+                CoreSettings::getInstance().softDebugLevelConsole_ = level;
+            else if (device == OutputHandler::LD_Logfile)
+                CoreSettings::getInstance().softDebugLevelLogfile_ = level;
+            else if (device == OutputHandler::LD_Shell)
+                CoreSettings::getInstance().softDebugLevelShell_ = level;
+        }
+     }
 
     /**
Index: code/trunk/src/core/CoreSettings.h
===================================================================
--- code/trunk/src/core/CoreSettings.h	(revision 1407)
+++ code/trunk/src/core/CoreSettings.h	(revision 1502)
@@ -54,4 +54,5 @@
 
             static int getSoftDebugLevel(OutputHandler::OutputDevice device = OutputHandler::LD_All);
+            static void setSoftDebugLevel(OutputHandler::OutputDevice device, int level);
             static const std::string& getLanguage();
             static void resetLanguage();
Index: code/trunk/src/core/Debug.h
===================================================================
--- code/trunk/src/core/Debug.h	(revision 1407)
+++ code/trunk/src/core/Debug.h	(revision 1502)
@@ -206,4 +206,13 @@
    COUT ## x
 
+  #if ORX_HARD_DEBUG_LEVEL >= ORX_NONE
+   #define COUT0  \
+    if (getSoftDebugLevel() >= ORX_NONE)  \
+     COUT_EXEC(0)
+  #else
+   #define COUT0 if (ORX_NONE)\
+    COUT_EXEC(0)
+  #endif
+
   #if ORX_HARD_DEBUG_LEVEL >= ORX_ERROR
    #define COUT1  \
@@ -256,6 +265,4 @@
  #endif /* if ORX_PRINT_DEBUG_OUTPUT */
 
- #define COUT0 \
-  COUT_EXEC(0)
 #endif /* ifndef COUT */
 
@@ -280,4 +287,13 @@
    CCOUT ## x
 
+  #if ORX_HARD_DEBUG_LEVEL >= ORX_NONE
+   #define CCOUT0  \
+    if (getSoftDebugLevel() >= ORX_NONE)  \
+     CCOUT_EXEC(0)
+  #else
+   #define CCOUT0 if (ORX_NONE)\
+    CCOUT_EXEC(0)
+  #endif
+
   #if ORX_HARD_DEBUG_LEVEL >= ORX_ERROR
    #define CCOUT1  \
@@ -330,6 +346,4 @@
  #endif /* if ORX_PRINT_DEBUG_OUTPUT */
 
- #define CCOUT0 \
-  CCOUT_EXEC(0)
 #endif /* ifndef CCOUT */
 
Index: code/trunk/src/core/Executor.cc
===================================================================
--- code/trunk/src/core/Executor.cc	(revision 1407)
+++ code/trunk/src/core/Executor.cc	(revision 1502)
@@ -34,12 +34,8 @@
 namespace orxonox
 {
-    Executor::Executor(Functor* functor, const std::string& name, AccessLevel::Level level)
+    Executor::Executor(Functor* functor, const std::string& name)
     {
         this->functor_ = functor;
         this->name_ = name;
-        this->accessLevel_ = level;
-        this->keybindMode_ = KeybindMode::OnPress;
-        this->axisParamIndex_ = -1;
-        this->bAxisRelative_ = false;
 
         this->bAddedDescription_ = false;
Index: code/trunk/src/core/Executor.h
===================================================================
--- code/trunk/src/core/Executor.h	(revision 1407)
+++ code/trunk/src/core/Executor.h	(revision 1502)
@@ -35,4 +35,5 @@
 #include "util/SubString.h"
 #include "util/String.h"
+#include "util/Math.h"
 #include "Functor.h"
 #include "Debug.h"
@@ -100,5 +101,5 @@
             COUT(5) << tokens[i]; \
         } \
-        COUT(5) << ") and " << (paramCount - tokens.size()) << " default values ("; \
+        COUT(5) << ") and " << max((int)paramCount - (int)tokens.size(), 0) << " default values ("; \
         for (unsigned int i = tokens.size(); i < paramCount; i++) \
         { \
@@ -134,17 +135,4 @@
     return true
 
-namespace AccessLevel
-{
-    enum Level
-    {
-        None,
-        User,
-        Admin,
-        Offline,
-        Debug,
-        Disabled
-    };
-}
-
 namespace orxonox
 {
@@ -152,5 +140,5 @@
     {
         public:
-            Executor(Functor* functor, const std::string& name = "", AccessLevel::Level level = AccessLevel::None);
+            Executor(Functor* functor, const std::string& name = "");
             virtual ~Executor();
 
@@ -181,4 +169,6 @@
             const std::string& getDescriptionReturnvalue(int param) const;
 
+            inline Functor* getFunctor() const
+                { return this->functor_; }
             inline unsigned int getParamCount() const
                 { return this->functor_->getParamCount(); }
@@ -199,24 +189,4 @@
                 { return this->name_; }
 
-            inline void setAccessLevel(AccessLevel::Level level)
-                { this->accessLevel_ = level; }
-            inline AccessLevel::Level getAccessLevel() const
-                { return this->accessLevel_; }
-
-            inline Executor& setKeybindMode(KeybindMode::Enum mode)
-                { this->keybindMode_ = mode; return *this; }
-            inline KeybindMode::Enum getKeybindMode() const
-                { return this->keybindMode_; }
-
-            inline Executor& setAxisParamIndex(int index)
-                { this->axisParamIndex_ = index; return *this; }
-            inline int getAxisParamIndex() const
-                { return this->axisParamIndex_; }
-
-            inline Executor& setIsAxisRelative(bool val)
-                { this->bAxisRelative_ = val; return *this; }
-            inline int getIsAxisRelative() const
-                { return this->bAxisRelative_; }
-
             Executor& setDefaultValues(const MultiTypeMath& param1);
             Executor& setDefaultValues(const MultiTypeMath& param1, const MultiTypeMath& param2);
@@ -249,8 +219,4 @@
             bool bAddedDefaultValue_[MAX_FUNCTOR_ARGUMENTS];
 
-            KeybindMode::Enum keybindMode_;
-            int axisParamIndex_;
-            bool bAxisRelative_;
-
         private:
             LanguageEntryLabel description_;
@@ -261,6 +227,4 @@
             bool bAddedDescriptionReturnvalue_;
             bool bAddedDescriptionParam_[MAX_FUNCTOR_ARGUMENTS];
-
-            AccessLevel::Level accessLevel_;
     };
 
@@ -268,5 +232,5 @@
     {
         public:
-            ExecutorStatic(FunctorStatic* functor, const std::string& name = "", AccessLevel::Level level = AccessLevel::None) : Executor(functor, name, level) {}
+            ExecutorStatic(FunctorStatic* functor, const std::string& name = "") : Executor(functor, name) {}
             virtual ~ExecutorStatic() {}
     };
@@ -276,5 +240,5 @@
     {
         public:
-            ExecutorMember(FunctorMember<T>* functor, const std::string& name = "", AccessLevel::Level level = AccessLevel::None) : Executor(functor, name, level) {}
+            ExecutorMember(FunctorMember<T>* functor, const std::string& name = "") : Executor(functor, name) {}
             virtual ~ExecutorMember() {}
 
@@ -322,18 +286,18 @@
     };
 
-    inline Executor* createExecutor(Functor* functor, const std::string& name = "", AccessLevel::Level level = AccessLevel::None)
-    {
-        return new Executor(functor, name, level);
+    inline Executor* createExecutor(Functor* functor, const std::string& name = "")
+    {
+        return new Executor(functor, name);
     }
 
     template <class T>
-    inline ExecutorMember<T>* createExecutor(FunctorMember<T>* functor, const std::string& name = "", AccessLevel::Level level = AccessLevel::None)
-    {
-        return new ExecutorMember<T>(functor, name, level);
+    inline ExecutorMember<T>* createExecutor(FunctorMember<T>* functor, const std::string& name = "")
+    {
+        return new ExecutorMember<T>(functor, name);
     }
 
-    inline ExecutorStatic* createExecutor(FunctorStatic* functor, const std::string& name = "", AccessLevel::Level level = AccessLevel::None)
-    {
-        return new ExecutorStatic(functor, name, level);
+    inline ExecutorStatic* createExecutor(FunctorStatic* functor, const std::string& name = "")
+    {
+        return new ExecutorStatic(functor, name);
     }
 }
Index: code/trunk/src/core/IRC.cc
===================================================================
--- code/trunk/src/core/IRC.cc	(revision 1502)
+++ code/trunk/src/core/IRC.cc	(revision 1502)
@@ -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:
+ *      ...
+ *
+ */
+
+#include <boost/thread/thread.hpp>
+
+#include "IRC.h"
+#include "ConsoleCommand.h"
+#include "TclThreadManager.h"
+#include "CoreIncludes.h"
+#include "util/Convert.h"
+
+#define IRC_TCL_THREADID 1421421421
+
+namespace orxonox
+{
+    SetConsoleCommand(IRC, say,  true).setAccessLevel(AccessLevel::User);
+    SetConsoleCommand(IRC, msg,  false).setAccessLevel(AccessLevel::User);
+    SetConsoleCommand(IRC, nick, false).setAccessLevel(AccessLevel::User);
+
+    IRC* instance_irc = &IRC::getInstance();
+
+    IRC::IRC()
+    {
+        RegisterRootObject(IRC);
+        this->bundle_ = 0;
+    }
+
+    void IRC::initialize()
+    {
+        unsigned int threadID = (unsigned int)IRC_TCL_THREADID;
+        TclThreadManager::createID(threadID);
+        this->bundle_ = TclThreadManager::getInstance().getInterpreterBundle(threadID);
+
+        try
+        {
+            this->bundle_->interpreter_->def("orxonox::irc::say", IRC::tcl_say, Tcl::variadic());
+            this->bundle_->interpreter_->def("orxonox::irc::privmsg", IRC::tcl_privmsg, Tcl::variadic());
+            this->bundle_->interpreter_->def("orxonox::irc::action", IRC::tcl_action, Tcl::variadic());
+            this->bundle_->interpreter_->def("orxonox::irc::info", IRC::tcl_info, Tcl::variadic());
+        }
+        catch (Tcl::tcl_error const &e)
+        {   COUT(1) << "Tcl (IRC) error: " << e.what();   }
+        catch (std::exception const &e)
+        {   COUT(1) << "Error while initializing Tcl (IRC): " << e.what();   }
+
+        this->nickname_ = "orx" + getConvertedValue<int, std::string>((unsigned int)rand());
+        TclThreadManager::execute(threadID, "set nickname " + this->nickname_);
+        TclThreadManager::execute(threadID, "source irc.tcl");
+    }
+
+    IRC& IRC::getInstance()
+    {
+        static IRC instance;
+        return instance;
+    }
+
+    bool IRC::eval(const std::string& command)
+    {
+        if (!IRC::getInstance().bundle_)
+        {
+            IRC::getInstance().initialize();
+            COUT(1) << "Error: IRC client wasn't yet initialized, please try again." << std::endl;
+            return false;
+        }
+
+        try
+        {
+            IRC::getInstance().bundle_->interpreter_->eval(command);
+            return true;
+        }
+        catch (Tcl::tcl_error const &e)
+        {   COUT(1) << "Tcl (IRC) error: " << e.what();   }
+        catch (std::exception const &e)
+        {   COUT(1) << "Error while executing Tcl (IRC): " << e.what();   }
+
+        return false;
+    }
+
+    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));
+    }
+
+    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));
+    }
+
+    void IRC::nick(const std::string& nickname)
+    {
+        if (IRC::eval("irk::nick $conn " + nickname))
+            IRC::getInstance().nickname_ = nickname;
+    }
+
+    void IRC::tcl_say(Tcl::object const &channel, Tcl::object const &nick, Tcl::object const &args)
+    {
+        COUT(0) << "IRC> " << nick.get() << ": " << stripEnclosingBraces(args.get()) << std::endl;
+    }
+
+    void IRC::tcl_privmsg(Tcl::object const &query, Tcl::object const &nick, Tcl::object const &args)
+    {
+        COUT(0) << "IRC (" << query.get() << ")> " << nick.get() << ": " << stripEnclosingBraces(args.get()) << std::endl;
+    }
+
+    void IRC::tcl_action(Tcl::object const &channel, Tcl::object const &nick, Tcl::object const &args)
+    {
+        COUT(0) << "IRC> * " << nick.get() << " " << stripEnclosingBraces(args.get()) << std::endl;
+    }
+
+    void IRC::tcl_info(Tcl::object const &channel, Tcl::object const &args)
+    {
+        COUT(0) << "IRC> --> " << stripEnclosingBraces(args.get()) << std::endl;
+    }
+}
Index: code/trunk/src/core/IRC.h
===================================================================
--- code/trunk/src/core/IRC.h	(revision 1502)
+++ code/trunk/src/core/IRC.h	(revision 1502)
@@ -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 _IRC_H__
+#define _IRC_H__
+
+#include "CorePrereqs.h"
+
+#include "OrxonoxClass.h"
+#include "cpptcl/CppTcl.h"
+
+namespace orxonox
+{
+    class _CoreExport IRC : public OrxonoxClass
+    {
+        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(const IRC& other);
+            ~IRC() {}
+
+            TclInterpreterBundle* bundle_;
+            std::string nickname_;
+    };
+}
+
+#endif /* _IRC_H__ */
Index: code/trunk/src/core/Identifier.cc
===================================================================
--- code/trunk/src/core/Identifier.cc	(revision 1407)
+++ code/trunk/src/core/Identifier.cc	(revision 1502)
@@ -37,5 +37,5 @@
 
 #include "Factory.h"
-#include "Executor.h"
+#include "ConsoleCommand.h"
 #include "CommandExecutor.h"
 
@@ -231,4 +231,10 @@
     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())
+        {
+            COUT(2) << "Warning: Overwriting config-value with name " << varname << " in class " << this->getName() << "." << std::endl;
+        }
+
         this->bHasConfigValues_ = true;
         this->configValues_[varname] = container;
@@ -270,14 +276,20 @@
         @return The executor of the command
     */
-    ExecutorStatic& Identifier::addConsoleCommand(ExecutorStatic* executor, bool bCreateShortcut)
-    {
+    ConsoleCommand& Identifier::addConsoleCommand(ConsoleCommand* command, bool bCreateShortcut)
+    {
+        std::map<std::string, ConsoleCommand*>::const_iterator it = this->consoleCommands_.find(command->getName());
+        if (it != this->consoleCommands_.end())
+        {
+            COUT(2) << "Warning: Overwriting console-command with name " << command->getName() << " in class " << this->getName() << "." << std::endl;
+        }
+
         this->bHasConsoleCommands_ = true;
-        this->consoleCommands_[executor->getName()] = executor;
-        this->consoleCommands_LC_[getLowercase(executor->getName())] = executor;
+        this->consoleCommands_[command->getName()] = command;
+        this->consoleCommands_LC_[getLowercase(command->getName())] = command;
 
         if (bCreateShortcut)
-            CommandExecutor::addConsoleCommandShortcut(executor);
-
-        return (*executor);
+            CommandExecutor::addConsoleCommandShortcut(command);
+
+        return (*command);
     }
 
@@ -287,7 +299,7 @@
         @return The executor of the requested console command
     */
-    ExecutorStatic* Identifier::getConsoleCommand(const std::string& name) const
-    {
-        std::map<std::string, ExecutorStatic*>::const_iterator it = this->consoleCommands_.find(name);
+    ConsoleCommand* Identifier::getConsoleCommand(const std::string& name) const
+    {
+        std::map<std::string, ConsoleCommand*>::const_iterator it = this->consoleCommands_.find(name);
         if (it != this->consoleCommands_.end())
             return (*it).second;
@@ -301,7 +313,7 @@
         @return The executor of the requested console command
     */
-    ExecutorStatic* Identifier::getLowercaseConsoleCommand(const std::string& name) const
-    {
-        std::map<std::string, ExecutorStatic*>::const_iterator it = this->consoleCommands_LC_.find(name);
+    ConsoleCommand* Identifier::getLowercaseConsoleCommand(const std::string& name) const
+    {
+        std::map<std::string, ConsoleCommand*>::const_iterator it = this->consoleCommands_LC_.find(name);
         if (it != this->consoleCommands_LC_.end())
             return (*it).second;
Index: code/trunk/src/core/Identifier.h
===================================================================
--- code/trunk/src/core/Identifier.h	(revision 1407)
+++ code/trunk/src/core/Identifier.h	(revision 1502)
@@ -63,4 +63,5 @@
 #include "Debug.h"
 #include "Iterator.h"
+#include "MetaObjectList.h"
 #include "util/String.h"
 
@@ -175,16 +176,16 @@
 
             /** @brief Returns the map that stores all console commands. @return The const_iterator */
-            inline const std::map<std::string, ExecutorStatic*>& getConsoleCommandMap() const { return this->consoleCommands_; }
+            inline const std::map<std::string, ConsoleCommand*>& getConsoleCommandMap() const { return this->consoleCommands_; }
             /** @brief Returns a const_iterator to the beginning of the map that stores all console commands. @return The const_iterator */
-            inline std::map<std::string, ExecutorStatic*>::const_iterator getConsoleCommandMapBegin() const { return this->consoleCommands_.begin(); }
+            inline std::map<std::string, ConsoleCommand*>::const_iterator getConsoleCommandMapBegin() const { return this->consoleCommands_.begin(); }
             /** @brief Returns a const_iterator to the end of the map that stores all console commands. @return The const_iterator */
-            inline std::map<std::string, ExecutorStatic*>::const_iterator getConsoleCommandMapEnd() const { return this->consoleCommands_.end(); }
+            inline std::map<std::string, ConsoleCommand*>::const_iterator getConsoleCommandMapEnd() const { return this->consoleCommands_.end(); }
 
             /** @brief Returns the map that stores all console commands with their names in lowercase. @return The const_iterator */
-            inline const std::map<std::string, ExecutorStatic*>& getLowercaseConsoleCommandMap() const { return this->consoleCommands_LC_; }
+            inline const std::map<std::string, ConsoleCommand*>& getLowercaseConsoleCommandMap() const { return this->consoleCommands_LC_; }
             /** @brief Returns a const_iterator to the beginning of the map that stores all console commands with their names in lowercase. @return The const_iterator */
-            inline std::map<std::string, ExecutorStatic*>::const_iterator getLowercaseConsoleCommandMapBegin() const { return this->consoleCommands_LC_.begin(); }
+            inline std::map<std::string, ConsoleCommand*>::const_iterator getLowercaseConsoleCommandMapBegin() const { return this->consoleCommands_LC_.begin(); }
             /** @brief Returns a const_iterator to the end of the map that stores all console commands with their names in lowercase. @return The const_iterator */
-            inline std::map<std::string, ExecutorStatic*>::const_iterator getLowercaseConsoleCommandMapEnd() const { return this->consoleCommands_LC_.end(); }
+            inline std::map<std::string, ConsoleCommand*>::const_iterator getLowercaseConsoleCommandMapEnd() const { return this->consoleCommands_LC_.end(); }
 
 
@@ -213,7 +214,7 @@
             virtual XMLPortObjectContainer* getXMLPortObjectContainer(const std::string& sectionname) = 0;
 
-            ExecutorStatic& addConsoleCommand(ExecutorStatic* executor, bool bCreateShortcut);
-            ExecutorStatic* getConsoleCommand(const std::string& name) const;
-            ExecutorStatic* getLowercaseConsoleCommand(const std::string& name) const;
+            ConsoleCommand& addConsoleCommand(ConsoleCommand* command, bool bCreateShortcut);
+            ConsoleCommand* getConsoleCommand(const std::string& name) const;
+            ConsoleCommand* getLowercaseConsoleCommand(const std::string& name) const;
 
         protected:
@@ -270,6 +271,6 @@
 
             bool bHasConsoleCommands_;                                     //!< True if this class has at least one assigned console command
-            std::map<std::string, ExecutorStatic*> consoleCommands_;       //!< All console commands of this class
-            std::map<std::string, ExecutorStatic*> consoleCommands_LC_;    //!< All console commands of this class with their names in lowercase
+            std::map<std::string, ConsoleCommand*> consoleCommands_;       //!< All console commands of this class
+            std::map<std::string, ConsoleCommand*> consoleCommands_LC_;    //!< All console commands of this class with their names in lowercase
     };
 
Index: code/trunk/src/core/InputBuffer.cc
===================================================================
--- code/trunk/src/core/InputBuffer.cc	(revision 1407)
+++ code/trunk/src/core/InputBuffer.cc	(revision 1502)
@@ -37,179 +37,221 @@
 namespace orxonox
 {
-  InputBuffer::InputBuffer(const std::string allowedChars) :
-    buffer_(""),
-    allowedChars_(allowedChars),
-    lastKey_(KeyCode::Unassigned),
-    timeSinceKeyPressed_(0.0f),
-    timeSinceKeyRepeated_(0.0f),
-    keysToRepeat_(0)
-  {
-    RegisterObject(InputBuffer);
-    setConfigValues();
-  }
-
-  void InputBuffer::setConfigValues()
-  {
-    SetConfigValue(keyRepeatDeleay_, 0.4).description("Key repeat deleay 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::registerListener(InputBufferListener* listener, void (InputBufferListener::*function)(), bool bOnlySingleInput)
-  {
-    struct InputBufferListenerTuple newListener = {listener, function, true, bOnlySingleInput, ' '};
-    listeners_.insert(listeners_.end(), newListener);
-  }
-
-  void InputBuffer::registerListener(InputBufferListener* listener, void (InputBufferListener::*function)(), char char_, bool bOnlySingleInput)
-  {
-    struct InputBufferListenerTuple newListener = {listener, function, false, bOnlySingleInput, char_};
-    listeners_.insert(listeners_.end(), newListener);
-  }
-  */
-  void InputBuffer::set(const std::string& input)
-  {
-    buffer_ = "";
-    append(input);
-  }
-
-  void InputBuffer::append(const std::string& input)
-  {
-    for (unsigned int i = 0; i < input.size(); i++)
-    {
-      if (charIsAllowed(input[i]))
-        buffer_ += input[i];
-
-      updated(input[i], false);
-    }
-    updated();
-  }
-
-  void InputBuffer::append(const char& input)
-  {
-    if (charIsAllowed(input))
-      buffer_ += input;
-
-    updated(input, true);
-  }
-
-  void InputBuffer::clear()
-  {
-    buffer_ = "";
-    updated();
-  }
-
-  void InputBuffer::removeLast()
-  {
-    buffer_ = buffer_.substr(0, buffer_.size() - 1);
-    updated();
-  }
-
-  void InputBuffer::updated()
-  {
-    for (std::list<InputBufferListenerTuple>::iterator it = listeners_.begin(); it != listeners_.end(); ++it)
-    {
-      if ((*it).bListenToAllChanges_)
-        (*(*it).listener_.*(*it).function_)();
-    }
-  }
-
-  void InputBuffer::updated(const char& update, bool bSingleInput)
-  {
-    for (std::list<InputBufferListenerTuple>::iterator it = listeners_.begin(); it != listeners_.end(); ++it)
-    {
-      if (((*it).bListenToAllChanges_ || ((*it).char_ == update)) && (!(*it).bOnlySingleInput_ || bSingleInput))
-        (*(*it).listener_.*(*it).function_)();
-    }
-  }
-
-  bool InputBuffer::charIsAllowed(const char& input)
-  {
-    if (allowedChars_ == "")
-      return true;
-    else
-      return (allowedChars_.find(input) != std::string::npos);
-  }
-
-
-  void InputBuffer::processKey(const KeyEvent &evt)
-  {
-    if (evt.isModifierDown(KeyboardModifier::Ctrl))
-    {
-      if (evt.key == KeyCode::V)
-        append(fromClipboard());
-      else if (evt.key == KeyCode::C)
-        toClipboard(buffer_);
-      else if (evt.key == KeyCode::X)
-      {
-        toClipboard(buffer_);
-        clear();
-      }
-    }
-    else if (evt.isModifierDown(KeyboardModifier::Shift))
-    {
-      if (evt.key == KeyCode::Insert)
-      {
-        append(fromClipboard());
-      }
-      else if (evt.key == KeyCode::Delete)
-      {
-        toClipboard(buffer_);
-        clear();
-      }
-    }
-    //std::string input = keyboard_->getAsString(e.key);
-    /*if (input.size() >= 1)
-    append(input[0]);*/
-
-    append((char)evt.text);
-  }
-
-  /**
-  * This tick() function is called by the InputManager if the InputBuffer is active.
-  * @param dt Delta time
-  */
-  void InputBuffer::tick(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::keyPressed(const KeyEvent &evt)
-  {
-    lastKey_ = evt.key;
-    timeSinceKeyPressed_ = 0.0;
-    timeSinceKeyRepeated_ = keyRepeatDeleay_;
-    keysToRepeat_ = 0;
-
-    processKey(evt);
-  }
-
-  void InputBuffer::keyHeld(const KeyEvent& evt)
-  {
-    if (evt.key == lastKey_)
-    {
-      while (keysToRepeat_)
-      {
+    InputBuffer::InputBuffer()
+    {
+        RegisterObject(InputBuffer);
+
+        this->buffer_ = "";
+        this->cursor_ = 0;
+        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->allowedChars_ = allowedChars;
+        this->buffer_ = "";
+        this->cursor_ = 0;
+
+        this->lastKey_ = KeyCode::Unassigned;
+        this->timeSinceKeyPressed_ = 0.0f;
+        this->timeSinceKeyRepeated_ = 0.0f;
+        this->keysToRepeat_ = 0;
+
+        setConfigValues();
+    }
+
+    void InputBuffer::setConfigValues()
+    {
+        SetConfigValue(keyRepeatDeleay_, 0.4).description("Key repeat deleay 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::set(const std::string& input, bool update)
+    {
+        this->clear(false);
+        this->insert(input, update);
+    }
+
+    void InputBuffer::insert(const std::string& input, bool update)
+    {
+        for (unsigned int i = 0; i < input.size(); ++i)
+        {
+            this->insert(input[i], false);
+
+            if (update)
+                this->updated(input[i], false);
+        }
+
+        if (update)
+            this->updated();
+    }
+
+    void InputBuffer::insert(const char& input, bool update)
+    {
+        if (this->charIsAllowed(input))
+        {
+            this->buffer_.insert(this->cursor_, 1, input);
+            ++this->cursor_;
+        }
+
+        if (update)
+            this->updated(input, true);
+    }
+
+    void InputBuffer::clear(bool update)
+    {
+        this->buffer_ = "";
+        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 (std::list<BaseInputBufferListenerTuple*>::iterator it = this->listeners_.begin(); it != this->listeners_.end(); ++it)
+        {
+            if ((*it)->bListenToAllChanges_)
+                (*it)->callFunction();
+        }
+    }
+
+    void InputBuffer::updated(const char& update, bool bSingleInput)
+    {
+        for (std::list<BaseInputBufferListenerTuple*>::iterator it = this->listeners_.begin(); it != this->listeners_.end(); ++it)
+        {
+            if ((!(*it)->trueKeyFalseChar_) && ((*it)->bListenToAllChanges_ || ((*it)->char_ == update)) && (!(*it)->bOnlySingleInput_ || bSingleInput))
+                (*it)->callFunction();
+        }
+    }
+
+    bool InputBuffer::charIsAllowed(const char& input)
+    {
+        if (this->allowedChars_ == "")
+            return true;
+        else
+            return (this->allowedChars_.find(input) != std::string::npos);
+    }
+
+
+    void InputBuffer::processKey(const KeyEvent &evt)
+    {
+        if (evt.isModifierDown(KeyboardModifier::Alt) && evt.key == KeyCode::Tab)
+            return;
+
+        for (std::list<BaseInputBufferListenerTuple*>::iterator it = this->listeners_.begin(); it != this->listeners_.end(); ++it)
+        {
+            if ((*it)->trueKeyFalseChar_ && ((*it)->key_ == evt.key))
+                (*it)->callFunction();
+        }
+
+        if (evt.isModifierDown(KeyboardModifier::Ctrl))
+        {
+            if (evt.key == KeyCode::V)
+                this->insert(fromClipboard());
+            else if (evt.key == KeyCode::C)
+                toClipboard(this->buffer_);
+            else if (evt.key == KeyCode::X)
+            {
+                toClipboard(this->buffer_);
+                this->clear();
+            }
+        }
+        else if (evt.isModifierDown(KeyboardModifier::Shift))
+        {
+            if (evt.key == KeyCode::Insert)
+                this->insert(fromClipboard());
+            else if (evt.key == KeyCode::Delete)
+            {
+                toClipboard(this->buffer_);
+                this->clear();
+            }
+        }
+
+        this->insert((char)evt.text);
+    }
+
+    /**
+        @brief This tick() function is called by the InputManager if the InputBuffer is active.
+        @param dt Delta time
+    */
+    void InputBuffer::tickInput(float dt, const HandlerState& state)
+    {
+        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::keyPressed(const KeyEvent &evt)
+    {
+        lastKey_ = evt.key;
+        timeSinceKeyPressed_ = 0.0;
+        timeSinceKeyRepeated_ = keyRepeatDeleay_;
+        keysToRepeat_ = 0;
+
         processKey(evt);
-        keysToRepeat_--;
-      }
-    }
-  }
-
+    }
+
+    void InputBuffer::keyHeld(const KeyEvent& evt)
+    {
+        if (evt.key == lastKey_)
+        {
+            while (keysToRepeat_)
+            {
+                processKey(evt);
+                keysToRepeat_--;
+            }
+        }
+    }
 }
Index: code/trunk/src/core/InputBuffer.h
===================================================================
--- code/trunk/src/core/InputBuffer.h	(revision 1407)
+++ code/trunk/src/core/InputBuffer.h	(revision 1502)
@@ -36,90 +36,153 @@
 
 #include "InputInterfaces.h"
-#include "Tickable.h"
+#include "OrxonoxClass.h"
 
 namespace orxonox
 {
-  class _CoreExport InputBufferListener
-  {};
-
-  class _CoreExport InputBuffer : public KeyHandler, public OrxonoxClass
-  {
-    struct InputBufferListenerTuple
+    class BaseInputBufferListenerTuple
     {
-      InputBufferListener* listener_;
-      void (InputBufferListener::*function_)();
-      bool bListenToAllChanges_;
-      bool bOnlySingleInput_;
-      char char_;
+    public:
+        BaseInputBufferListenerTuple(bool bListenToAllChanges, bool bOnlySingleInput,
+            bool trueKeyFalseChar, char _char, KeyCode::Enum key)
+            : bListenToAllChanges_(bListenToAllChanges), bOnlySingleInput_(bOnlySingleInput),
+              trueKeyFalseChar_(trueKeyFalseChar), char_(_char), key_(key)
+        { }
+        virtual ~BaseInputBufferListenerTuple() { }
+        virtual void callFunction() = 0;
+        bool bListenToAllChanges_;
+        bool bOnlySingleInput_;
+        bool trueKeyFalseChar_;
+        char char_;
+        KeyCode::Enum key_;
     };
 
-  public:
-    InputBuffer(const std::string allowedChars =
-      "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZäöüÄÖÜ0123456789 \\\"(){}[]<>.:,;_-+*/=!?|$&%^");
+    template <class T>
+    class InputBufferListenerTuple : public BaseInputBufferListenerTuple
+    {
+    public:
+        InputBufferListenerTuple(T* listener, void (T::*function)(), bool bListenToAllChanges,
+            bool bOnlySingleInput, bool trueKeyFalseChar, char _char, KeyCode::Enum key)
+            : BaseInputBufferListenerTuple(bListenToAllChanges, bOnlySingleInput, trueKeyFalseChar, _char, key),
+              listener_(listener), function_(function)
+        { }
+        virtual ~InputBufferListenerTuple() { }
+        void callFunction()
+        {
+            (listener_->*function_)();
+        }
+        T* listener_;
+        void (T::*function_)();
+    };
 
-    void setConfigValues();
+    class _CoreExport InputBuffer : public KeyHandler, public OrxonoxClass
+    {
+        public:
+            InputBuffer();
+            InputBuffer(const std::string allowedChars);
 
-    template <class T>
-    void registerListener(T* listener, void (T::*function)(), bool bOnlySingleInput)
-    {
-      struct InputBufferListenerTuple newListener = {listener, (void (InputBufferListener::*)())function, true, bOnlySingleInput, ' '};
-      this->listeners_.insert(this->listeners_.end(), newListener);
-    }
-    template <class T>
-    void registerListener(T* listener, void (T::*function)() const, bool bOnlySingleInput)
-    {
-      struct InputBufferListenerTuple newListener = {listener, (void (InputBufferListener::*)())function, true, bOnlySingleInput, ' '};
-      this->listeners_.insert(this->listeners_.end(), newListener);
-    }
+            void setConfigValues();
 
-    template <class T>
-    void registerListener(T* listener, void (T::*function)(), char char_, bool bOnlySingleInput)
-    {
-      struct InputBufferListenerTuple newListener = {listener, (void (InputBufferListener::*)())function, false, bOnlySingleInput, char_};
-      this->listeners_.insert(this->listeners_.end(), newListener);
-    }
-    template <class T>
-    void registerListener(T* listener, void (T::*function)() const, char char_, bool bOnlySingleInput)
-    {
-      struct InputBufferListenerTuple newListener = {listener, (void (InputBufferListener::*)())function, false, bOnlySingleInput, char_};
-      this->listeners_.insert(this->listeners_.end(), newListener);
-    }
+            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);
+            }
 
-    void set(const std::string& input);
-    void append(const std::string& input);
-    void append(const char& input);
-    void removeLast();
-    void clear();
+            template <class T>
+            void registerListener(T* listener, void (T::*function)(), KeyCode::Enum 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::Enum key)
+            {
+                InputBufferListenerTuple<T>* newTuple = new InputBufferListenerTuple<T>(listener, (void (T::*)())function, false, true, true, '\0', key);
+                this->listeners_.insert(this->listeners_.end(), newTuple);
+            }
 
-    void updated();
-    void updated(const char& update, bool bSingleInput);
+            template <class T>
+            void unregisterListener(T* listener)
+            {
+                for (std::list<BaseInputBufferListenerTuple*>::iterator it = this->listeners_.begin(); it != this->listeners_.end(); )
+                {
+                    InputBufferListenerTuple<T>* refListener = dynamic_cast<InputBufferListenerTuple<T>*>(*it);
+                    if (refListener && refListener->listener_ == listener)
+                        this->listeners_.erase(it++);
+                    else
+                        it++;
+                }
+            }
 
-    inline std::string get() const
-    { return this->buffer_; }
+            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);
 
-  private:  // functions
-    bool charIsAllowed(const char& input);
+            void updated();
+            void updated(const char& update, bool bSingleInput);
 
-    void keyPressed (const KeyEvent& evt);
-    void keyReleased(const KeyEvent& evt) { }
-    void keyHeld    (const KeyEvent& evt);
-    void processKey (const KeyEvent &e);
+            inline std::string get() const
+                { return this->buffer_; }
+            inline unsigned int getSize() const
+                { return this->buffer_.size(); }
 
-    void tick(float dt);
+            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_; } }
 
-  private: // variables
-    std::string buffer_;
-    std::list<InputBufferListenerTuple> listeners_;
-    std::string allowedChars_;
+        private:
+            bool charIsAllowed(const char& input);
 
-    KeyCode::Enum lastKey_;
-    float timeSinceKeyPressed_;
-    float timeSinceKeyRepeated_;
-    int keysToRepeat_;
+            void keyPressed (const KeyEvent& evt);
+            void keyReleased(const KeyEvent& evt) { }
+            void keyHeld    (const KeyEvent& evt);
+            void processKey (const KeyEvent &e);
 
-    // configured values
-    float keyRepeatDeleay_;
-    float keyRepeatTime_;
-  };
+            void tickInput(float dt, const HandlerState& state);
+
+            std::string buffer_;
+            std::list<BaseInputBufferListenerTuple*> listeners_;
+            std::string allowedChars_;
+            unsigned int cursor_;
+
+            KeyCode::Enum lastKey_;
+            float timeSinceKeyPressed_;
+            float timeSinceKeyRepeated_;
+            int keysToRepeat_;
+
+            float keyRepeatDeleay_;
+            float keyRepeatTime_;
+    };
 }
 
Index: code/trunk/src/core/InputHandler.cc
===================================================================
--- code/trunk/src/core/InputHandler.cc	(revision 1407)
+++ 	(revision )
@@ -1,811 +1,0 @@
-/*
- *   ORXONOX - the hottest 3D action shooter ever to exist
- *                    > www.orxonox.net <
- *
- *
- *   License notice:
- *
- *   This program is free software; you can redistribute it and/or
- *   modify it under the terms of the GNU General Public License
- *   as published by the Free Software Foundation; either version 2
- *   of the License, or (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   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 "InputHandler.h"
-#include "util/Convert.h"
-#include "util/SubString.h"
-#include "util/String.h"
-#include "Debug.h"
-#include "ConfigValueIncludes.h"
-#include "CoreIncludes.h"
-#include "CommandExecutor.h"
-#include "Executor.h"
-
-namespace orxonox
-{
-  // ###############################
-  // ######      Button       ######
-  // ###############################
-
-  bool BufferedParamCommand::execute()
-  {
-    if (nValuesAdded_)
-    {
-      BufferedParamCommand& cmd = *this;
-      cmd.evaluation_.setEvaluatedParameter(cmd.paramIndex_, cmd.value_);
-      // reset
-      cmd.nValuesAdded_ = 0;
-      cmd.value_ = 0;
-      return CommandExecutor::execute(cmd.evaluation_);
-    }
-    else
-      return true;
-  }
-
-  bool SimpleCommand::execute(float abs, float rel)
-  {
-    return CommandExecutor::execute(evaluation_);
-  }
-
-  bool ParamCommand::execute(float abs, float rel)
-  {
-    BufferedParamCommand& paramCommand = *paramCommand_;
-    // command has an additional parameter
-    if (bRelative_ && (rel > 0 || rel < 0))
-    {
-      // we have to calculate a relative movement.
-      // paramModifier_ says how much one keystroke is
-      paramCommand.value_ += paramModifier_ * rel;
-    }
-    else if (abs > 0 || abs < 0)
-    {
-      // we have to calculate absolute position of the axis.
-      // Since there might be another axis that is affected, we have to wait and
-      // store the result in a temporary place
-      paramCommand.value_ = (paramCommand.value_ * paramCommand.nValuesAdded_ + paramModifier_ * abs)
-                            /++paramCommand.nValuesAdded_;
-    }
-    return true;
-  }
-
-  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] = 0;
-        nCommands_[j] = 0;
-      }
-      else
-      {
-        commands_[j] = 0;
-      }
-    }
-  }
-
-  void Button::parse(std::vector<BufferedParamCommand*>& paramCommandBuffer)
-  {
-    if (isEmpty(bindingString_))
-    {
-      clear();
-      return;
-    }
-
-    // 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] != "")
-      {
-        SubString tokens(commandStrings[iCommand], " ", SubString::WhiteSpaces, false,
-            '\\', false, '"', false, '(', ')', false, '\0');
-        
-        unsigned int iToken = 0;
-
-        // for real axes, we can feed a ButtonThreshold argument as entire command
-        if (getLowercase(tokens[0]) == "buttonthreshold")
-        {
-          if (tokens.size() == 1)
-            continue;
-          // may fail, but doesn't matter
-          convertValue(&buttonThreshold_, tokens[1]);
-          continue;
-        }
-
-        // first argument can be OnPress, OnHold OnRelease or nothing
-        KeybindMode::Enum mode = KeybindMode::None;
-        if (getLowercase(tokens[iToken]) == "onpress")
-          mode = KeybindMode::OnPress,   iToken++;
-        if (getLowercase(tokens[iToken]) == "onrelease")
-          mode = KeybindMode::OnRelease, iToken++;
-        if (getLowercase(tokens[iToken]) == "onhold")
-          mode = KeybindMode::OnHold,    iToken++;
-
-        if (iToken == tokens.size())
-          continue;
-
-        // second argument can be the amplitude for the case it as an axis command
-        // default amplitude is 1.0f
-        float paramModifier = 1.0f;
-        if (getLowercase(tokens[iToken]) == "axisamp")
-        {
-          iToken++;
-          if (iToken == tokens.size() || !convertValue(&paramModifier, tokens[iToken]))
-          {
-            COUT(2) << "Error while parsing key binding " << name_
-                << ". Numeric expression expected afer 'AxisAmp', switching to default value" << std::endl;
-            if (iToken == tokens.size())
-              continue;
-          }
-          iToken++;
-        }
-
-        // no more arguments expected except for the actual command
-        if (iToken == tokens.size())
-          continue;
-
-        std::string commandStr;
-        while (iToken != tokens.size())
-          commandStr += tokens[iToken++] + " ";
-
-        // evaluate the command
-        CommandEvaluation eval = CommandExecutor::evaluate(commandStr);
-        if (!eval.isValid())
-          continue;
-
-        // check for param command
-        int paramIndex = eval.getEvaluatedExecutor()->getAxisParamIndex();
-        // TODO: check in Executor for correct paramIndex
-        if (paramIndex >= 0)
-        {
-          // parameter supported command
-          ParamCommand* cmd = new ParamCommand();
-          cmd->paramModifier_ = paramModifier;
-          cmd->bRelative_ = eval.getEvaluatedExecutor()->getIsAxisRelative();
-
-          // add command to the buffer if not yet existing
-          for (unsigned int iParamCmd = 0; iParamCmd < paramCommandBuffer.size(); iParamCmd++)
-          {
-            if (getLowercase(paramCommandBuffer[iParamCmd]->evaluation_.getCommandString())
-                == getLowercase(commandStr))
-            {
-              // already in list
-              cmd->paramCommand_ = paramCommandBuffer[iParamCmd];
-              break;
-            }
-          }
-          if (cmd->paramCommand_ == 0)
-          {
-            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)
-          {
-            if (!addParamCommand(cmd))
-            {
-              mode = eval.getEvaluatedExecutor()->getKeybindMode();
-              commands[mode].push_back(cmd);
-            }
-          }
-        }
-        else
-        {
-          SimpleCommand* cmd = new SimpleCommand();
-          cmd->evaluation_ = eval;
-
-          //TODO: check CommandEvaluation for correct KeybindMode
-          if (mode == KeybindMode::None)
-            mode = eval.getEvaluatedExecutor()->getKeybindMode();
-
-          commands[mode].push_back(cmd);
-        }
-      }
-    }
-
-    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] = 0;
-    }
-  }
-
-  bool Button::execute(KeybindMode::Enum 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;
-  }
-
-  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_;
-    }
-    else
-    {
-      nParamCommands_ = 0; 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;
-    delete[] cmds;
-    return true;
-  }
-
-  bool HalfAxis::execute()
-  {
-    bool success = true;
-    for (unsigned int i = 0; i < nParamCommands_; i++)
-      success = success && paramCommands_[i]->execute(absVal_, relVal_);
-    return success;
-  }
-
-
-  // ###############################
-  // ######     KeyBinder     ######
-  // ###############################
-
-  /**
-    @brief Constructor that does as little as necessary.
-  */
-  KeyBinder::KeyBinder() : deriveTime_(0.0f)
-  {
-    RegisterObject(KeyBinder);
-
-    // keys
-    std::string keyNames[] = {
-      "UNASSIGNED",
-      "ESCAPE",
-      "1", "2", "3", "4", "5", "6", "7", "8", "9", "0",
-      "MINUS", "EQUALS", "BACK", "TAB",
-      "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P",
-      "LBRACKET", "RBRACKET",
-      "RETURN", "LCONTROL",
-      "A", "S", "D", "F", "G", "H", "J", "K", "L",
-      "SEMICOLON", "APOSTROPHE", "GRAVE",
-      "LSHIFT", "BACKSLASH",
-      "Z", "X", "C", "V", "B", "N", "M",
-      "COMMA", "PERIOD", "SLASH",
-      "RSHIFT",
-      "MULTIPLY",
-      "LMENU",
-      "SPACE",
-      "CAPITAL",
-      "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10",
-      "NUMLOCK", "SCROLL",
-      "NUMPAD7", "NUMPAD8", "NUMPAD9",
-      "SUBTRACT",
-      "NUMPAD4", "NUMPAD5", "NUMPAD6",
-      "ADD",
-      "NUMPAD1", "NUMPAD2", "NUMPAD3", "NUMPAD0",
-      "DECIMAL",
-      "","",
-      "OEM_102",
-      "F11", "F12",
-      "","","","","","","","","","","",
-      "F13", "F14", "F15",
-      "","","","","","","","","","",
-      "KANA",
-      "","",
-      "ABNT_C1",
-      "","","","","",
-      "CONVERT",
-      "",
-      "NOCONVERT",
-      "",
-      "YEN",
-      "ABNT_C2",
-      "","","","","","","","","","","","","","",
-      "NUMPADEQUALS",
-      "","",
-      "PREVTRACK",
-      "AT",
-      "COLON", "UNDERLINE",
-      "KANJI",
-      "STOP",
-      "AX",
-      "UNLABELED",
-      "NEXTTRACK",
-      "","",
-      "NUMPADENTER",
-      "RCONTROL",
-      "","",
-      "MUTE",
-      "CALCULATOR",
-      "PLAYPAUSE",
-      "",
-      "MEDIASTOP",
-      "","","","","","","","","",
-      "VOLUMEDOWN",
-      "",
-      "VOLUMEUP",
-      "",
-      "WEBHOME",
-      "NUMPADCOMMA",
-      "",
-      "DIVIDE",
-      "",
-      "SYSRQ",
-      "RMENU",
-      "","","","","","","","","","","","",
-      "PAUSE",
-      "",
-      "HOME",
-      "UP",
-      "PGUP",
-      "",
-      "LEFT",
-      "",
-      "RIGHT",
-      "",
-      "END", "DOWN", "PGDOWN", "INSERT", "DELETE",
-      "","","","","","","",
-      "LWIN", "RWIN", "APPS",
-      "POWER", "SLEEP",
-      "","","",
-      "WAKE",
-      "",
-      "WEBSEARCH", "WEBFAVORITES", "WEBREFRESH", "WEBSTOP", "WEBFORWARD", "WEBBACK",
-      "MYCOMPUTER", "MAIL", "MEDIASELECT"
-    };
-    for (unsigned int i = 0; i < nKeys_s; i++)
-      keys_[i].name_ = "Key" + keyNames[i];
-
-    // mouse buttons
-    std::string mouseButtonNames[] = {
-      "MouseLeft", "MouseRight", "MouseMiddle",
-      "MouseButton3", "MouseButton4", "MouseButton5",
-      "MouseButton6", "MouseButton7",
-      "MouseWheel1Up", "MouseWheel1Down",
-      "MouseWheel2Up", "MouseWheel2Down" };
-    for (unsigned int i = 0; i < nMouseButtons_s; i++)
-      mouseButtons_[i].name_ = mouseButtonNames[i];
-
-    // joy stick buttons
-    for (unsigned int i = 0; i < 32; i++)
-      joyStickButtons_[i].name_ = "JoyButton" + getConvertedValue<int, std::string>(i);
-    for (unsigned int i = 32; i < nJoyStickButtons_s; i += 4)
-    {
-		  joyStickButtons_[i + 0].name_ = "JoyPOV" + getConvertedValue<int, std::string>((i - 32)/4 + 1) + "North";
-		  joyStickButtons_[i + 1].name_ = "JoyPOV" + getConvertedValue<int, std::string>((i - 32)/4 + 1) + "South";
-		  joyStickButtons_[i + 2].name_ = "JoyPOV" + getConvertedValue<int, std::string>((i - 32)/4 + 1) + "East";
-		  joyStickButtons_[i + 3].name_ = "JoyPOV" + getConvertedValue<int, std::string>((i - 32)/4 + 1) + "West";
-    }
-
-    // half axes
-    std::string rawNames[nHalfAxes_s/2];
-    rawNames[0] = "MouseX";
-    rawNames[1] = "MouseY";
-    rawNames[2] = "Empty1";
-    rawNames[3] = "Empty2";
-    for (unsigned int i = 4; i < nHalfAxes_s/2; i++)
-      rawNames[i] = "JoyAxis" + getConvertedValue<int, std::string>(i - 3);
-    for (unsigned int i = 0; i < nHalfAxes_s/2; i++)
-    {
-      halfAxes_[i * 2 + 0].name_ = rawNames[i] + "Pos";
-      halfAxes_[i * 2 + 1].name_ = rawNames[i] + "Neg";
-    }
-
-    for (unsigned int i = 0; i < this->nHalfAxes_s; i++)
-      halfAxes_[i].buttonThreshold_ = buttonThreshold_;
-  }
-
-  /**
-    @brief Destructor
-  */
-  KeyBinder::~KeyBinder()
-  {
-    // almost no destructors required because most of the arrays are static.
-    clearBindings(); // does some destruction work
-  }
-
-  /**
-    @brief Loads the key and button bindings.
-    @return True if loading succeeded.
-  */
-  void KeyBinder::loadBindings()
-  {
-    COUT(3) << "KeyBinder: Loading key bindings..." << std::endl;
-
-    ConfigFileManager::getSingleton()->setFile(CFT_Keybindings, "keybindings.ini");
-    clearBindings();
-    setConfigValues();
-
-    COUT(3) << "KeyBinder: Loading key bindings done." << std::endl;
-  }
-
-  /**
-    @brief Loader for the key bindings, managed by config values.
-  */
-  void KeyBinder::setConfigValues()
-  {
-    SetConfigValue(analogThreshold_, 0.01f)  .description("Threshold for analog axes until which the state is 0.");
-    SetConfigValue(bDeriveMouseInput_, false).description("Whether or not to derive moues movement for the absolute value.");
-    SetConfigValue(derivePeriod_, 0.1f)      .description("Accuracy of the mouse input deriver. The higher the more precise, but laggier.");
-    SetConfigValue(mouseSensitivity_, 1.0f)  .description("Mouse sensitivity.");
-
-    float oldThresh = buttonThreshold_;
-    SetConfigValue(buttonThreshold_, 0.80f).description("Threshold for analog axes until which the button is not pressed.");
-    if (oldThresh != buttonThreshold_)
-      for (unsigned int i = 0; i < nHalfAxes_s; i++)
-        if (halfAxes_[i].buttonThreshold_ == oldThresh)
-          halfAxes_[i].buttonThreshold_ = buttonThreshold_;
-
-    // keys
-    for (unsigned int i = 0; i < nKeys_s; i++)
-      readTrigger(keys_[i]);
-    // mouse buttons
-    for (unsigned int i = 0; i < nMouseButtons_s; i++)
-      readTrigger(mouseButtons_[i]);
-    // joy stick buttons
-    for (unsigned int i = 0; i < nJoyStickButtons_s; i++)
-      readTrigger(joyStickButtons_[i]);
-    // half axes
-    for (unsigned int i = 0; i < nHalfAxes_s; i++)
-      readTrigger(halfAxes_[i]);
-  }
-
-  void KeyBinder::readTrigger(Button& button)
-  {
-    // config value stuff
-    ConfigValueContainer* cont = getIdentifier()->getConfigValueContainer(button.name_);
-    if (!cont)
-    {
-      cont = new ConfigValueContainer(CFT_Keybindings, getIdentifier(), button.name_, "");
-      getIdentifier()->addConfigValueContainer(button.name_, cont);
-    }
-    std::string old = button.bindingString_;
-    cont->getValue(&button.bindingString_);
-
-    // keybinder stuff
-    if (old != button.bindingString_)
-    {
-      // binding has changed
-      button.parse(paramCommandBuffer_);
-    }
-  }
-
-  /**
-    @brief Overwrites all bindings with ""
-  */
-  void KeyBinder::clearBindings(bool bInit)
-  {
-    for (unsigned int i = 0; i < nKeys_s; i++)
-      keys_[i].clear();
-
-    for (unsigned int i = 0; i < nMouseButtons_s; i++)
-      mouseButtons_[i].clear();
-
-    for (unsigned int i = 0; i < nJoyStickButtons_s; i++)
-      joyStickButtons_[i].clear();
-
-    for (unsigned int i = 0; i < nHalfAxes_s; i++)
-      halfAxes_[i].clear();
-
-    for (unsigned int i = 0; i < paramCommandBuffer_.size(); i++)
-      delete paramCommandBuffer_[i];
-    paramCommandBuffer_.clear();
-  }
-
-  void KeyBinder::tick(float dt)
-  {
-    // we have to process all the analog input since there is e.g. no 'mouseDoesntMove' event.
-    for (unsigned int i = 0; i < nHalfAxes_s; i++)
-    {
-      if (halfAxes_[i].hasChanged_)
-      {
-        if (!halfAxes_[i].wasDown_ && halfAxes_[i].absVal_ > halfAxes_[i].buttonThreshold_)
-        {
-          halfAxes_[i].wasDown_ = true;
-          if (halfAxes_[i].nCommands_[KeybindMode::OnPress])
-            halfAxes_[i].execute(KeybindMode::OnPress);
-        }
-        else if (halfAxes_[i].wasDown_ && halfAxes_[i].absVal_ < halfAxes_[i].buttonThreshold_)
-        {
-          halfAxes_[i].wasDown_ = false;
-          if (halfAxes_[i].nCommands_[KeybindMode::OnRelease])
-            halfAxes_[i].execute(KeybindMode::OnRelease);
-        }
-        if (halfAxes_[i].wasDown_)
-        {
-          if (halfAxes_[i].nCommands_[KeybindMode::OnHold])
-            halfAxes_[i].execute(KeybindMode::OnHold);
-        }
-        halfAxes_[i].hasChanged_ = false;
-      }
-
-      // these are the actually useful axis bindings for analog input AND output
-      if (halfAxes_[i].relVal_ > analogThreshold_ || halfAxes_[i].absVal_ > analogThreshold_)
-      {
-        halfAxes_[i].execute();
-      }
-    }
-
-    if (bDeriveMouseInput_)
-    {
-      if (deriveTime_ > derivePeriod_)
-      {
-        deriveTime_ = 0.0f;
-        //CCOUT(3) << "mouse abs: ";
-        for (int i = 0; i < 2; i++)
-        {
-          if (mouseRelative_[i] > 0)
-          {
-            halfAxes_[2*i + 0].absVal_ = mouseRelative_[i] * derivePeriod_ / 500 * mouseSensitivity_;
-            halfAxes_[2*i + 1].absVal_ = 0.0f;
-          }
-          else if (mouseRelative_[0] < 0)
-          {
-            halfAxes_[2*i + 0].absVal_ = 0.0f;
-            halfAxes_[2*i + 1].absVal_ = -mouseRelative_[i] * derivePeriod_ / 500 * mouseSensitivity_;
-          }
-          //COUT(3) << mouseRelative_[i] << " | ";
-          mouseRelative_[i] = 0;
-        }
-        //COUT(3) << std::endl;
-      }
-      else
-        deriveTime_ += dt;
-    }
-
-    // execute all buffered bindings (addional parameter)
-    for (unsigned int i = 0; i < paramCommandBuffer_.size(); i++)
-      paramCommandBuffer_[i]->execute();
-
-    // always reset the relative movement of the mouse
-    for (unsigned int i = 0; i < 8; i++)
-      halfAxes_[i].relVal_ = 0.0f;
-  }
-
-  void KeyBinder::keyPressed (const KeyEvent& evt)
-  { keys_[evt.key].execute(KeybindMode::OnPress); }
-
-  void KeyBinder::keyReleased(const KeyEvent& evt)
-  { keys_[evt.key].execute(KeybindMode::OnRelease); }
-
-  void KeyBinder::keyHeld    (const KeyEvent& evt)
-  { keys_[evt.key].execute(KeybindMode::OnHold); }
-
-
-  void KeyBinder::mouseButtonPressed (MouseButton::Enum id)
-  { mouseButtons_[id].execute(KeybindMode::OnPress); }
-
-  void KeyBinder::mouseButtonReleased(MouseButton::Enum id)
-  { mouseButtons_[id].execute(KeybindMode::OnRelease); }
-
-  void KeyBinder::mouseButtonHeld    (MouseButton::Enum id)
-  { mouseButtons_[id].execute(KeybindMode::OnHold); }
-
-
-  void KeyBinder::joyStickButtonPressed (int joyStickID, int button)
-  { joyStickButtons_[button].execute(KeybindMode::OnPress); }
-
-  void KeyBinder::joyStickButtonReleased(int joyStickID, int button)
-  { joyStickButtons_[button].execute(KeybindMode::OnRelease); }
-
-  void KeyBinder::joyStickButtonHeld    (int joyStickID, int button)
-  { joyStickButtons_[button].execute(KeybindMode::OnHold); }
-
-  /**
-    @brief Event handler for the mouseMoved Event.
-    @param e Mouse state information
-  */
-  void KeyBinder::mouseMoved(IntVector2 abs_, IntVector2 rel_, IntVector2 clippingSize)
-  {
-    if (!bDeriveMouseInput_)
-    {
-      // y axis of mouse input is inverted
-      int rel[] = { rel_.x, -rel_.y };
-
-      //COUT(3) << rel[0] << " | " << rel[1] << std::endl;
-
-      for (int i = 0; i < 2; i++)
-      {
-        if (rel[i])
-        {
-          // absolute
-          if (mousePosition_[i] >= 0)
-          {
-            mousePosition_[i] += rel[i];
-            halfAxes_[0 + 2*i].hasChanged_ = true;
-            if (mousePosition_[i] < 0)
-            {
-              halfAxes_[1 + 2*i].hasChanged_ = true;
-              halfAxes_[1 + 2*i].absVal_ = -((float)mousePosition_[i])/1024 * mouseSensitivity_;
-              halfAxes_[0 + 2*i].absVal_ =  0.0f;
-            }
-            else
-              halfAxes_[1 + 2*i].absVal_ =  ((float)mousePosition_[i])/1024 * mouseSensitivity_;
-          }
-          else
-          {
-            mousePosition_[i] += rel[i];
-            halfAxes_[1 + 2*i].hasChanged_ = true;
-            if (mousePosition_[i] > 0)
-            {
-              halfAxes_[0 + 2*i].hasChanged_ = true;
-              halfAxes_[0 + 2*i].absVal_ =  ((float)mousePosition_[i])/1024 * mouseSensitivity_;
-              halfAxes_[1 + 2*i].absVal_ =  0.0f;
-            }
-            else
-              halfAxes_[1 + 2*i].absVal_ = -((float)mousePosition_[i])/1024 * mouseSensitivity_;
-          }
-
-          // relative
-          if (rel[i] > 0)
-            halfAxes_[0 + 2*i].relVal_ =  ((float)rel[i])/1024 * mouseSensitivity_;
-          else
-            halfAxes_[1 + 2*i].relVal_ = -((float)rel[i])/1024 * mouseSensitivity_;
-        }
-      }
-    }
-    else
-    {
-      mouseRelative_[0] += rel_.x;
-      mouseRelative_[1] -= rel_.y;
-    }
-  }
-
-  /**
-    @brief Event handler for the mouseScrolled Event.
-    @param e Mouse state information
-  */
-  void KeyBinder::mouseScrolled(int abs, int rel)
-  {
-    //COUT(3) << mouseButtons_[8].name_ << "   " << abs << " | " << rel << std::endl;
-
-    if (rel > 0)
-      for (int i = 0; i < rel/120; i++)
-        mouseButtons_[8].execute(KeybindMode::OnPress, ((float)abs)/120.0f);
-    else
-      for (int i = 0; i < -rel/120; i++)
-        mouseButtons_[9].execute(KeybindMode::OnPress, ((float)abs)/120.0f);
-  }
-
-  void KeyBinder::joyStickAxisMoved(int joyStickID, int axis, int value)
-  {
-    // TODO: check whether 16 bit integer as general axis value is a good idea (works under windows)
-    CCOUT(3) << halfAxes_[8 + axis].name_ << std::endl;
-    if (value >= 0)
-    {
-      halfAxes_[8 + axis].absVal_ = ((float)value)/0x8000;
-      halfAxes_[8 + axis].relVal_ = ((float)value)/0x8000;
-      halfAxes_[8 + axis].hasChanged_ = true;
-    }
-    else
-    {
-      halfAxes_[8 + axis + 1].absVal_ = -((float)value)/0x8000;
-      halfAxes_[8 + axis + 1].relVal_ = -((float)value)/0x8000;
-      halfAxes_[8 + axis + 1].hasChanged_ = true;
-    }
-  }
-
-
-  // ###############################
-  // ###     GUIInputHandler     ###
-  // ###############################
-
-  ///**
-  //  @brief standard constructor
-  //*/
-  //GUIInputHandler::GUIInputHandler()
-  //{
-  //}
-
-  ///**
-  //  @brief Destructor
-  //*/
-  //GUIInputHandler::~GUIInputHandler()
-  //{
-  //}
-
-  ///**
-  //  @brief Event handler for the keyPressed Event.
-  //  @param e Event information
-  //*/
-  //bool GUIInputHandler::keyPressed(const OIS::KeyEvent &e)
-  //{
-    ////CEGUI::System::getSingleton().injectKeyDown( arg.key );
-    ////CEGUI::System::getSingleton().injectChar( arg.text );
-  //  return true;
-  //}
-
-  ///**
-  //  @brief Event handler for the keyReleased Event.
-  //  @param e Event information
-  //*/
-  //bool GUIInputHandler::keyReleased(const OIS::KeyEvent &e)
-  //{
-    ////CEGUI::System::getSingleton().injectKeyUp( arg.key );
-  //  return true;
-  //}
-
-  ///**
-  //  @brief Event handler for the mouseMoved Event.
-  //  @param e Event information
-  //*/
-  //bool GUIInputHandler::mouseMoved(const OIS::MouseEvent &e)
-  //{
-    ////CEGUI::System::getSingleton().injectMouseMove( arg.state.X.rel, arg.state.Y.rel );
-  //  return true;
-  //}
-
-  ///**
-  //  @brief Event handler for the mousePressed Event.
-  //  @param e Event information
-  //  @param id The ID of the mouse button
-  //*/
-  //bool GUIInputHandler::mousePressed(const OIS::MouseEvent &e, OIS::MouseButton id)
-  //{
-    ////CEGUI::System::getSingleton().injectMouseButtonDown(convertOISMouseButtonToCegui(id));
-  //  return true;
-  //}
-
-  ///**
-  //  @brief Event handler for the mouseReleased Event.
-  //  @param e Event information
-  //  @param id The ID of the mouse button
-  //*/
-  //bool GUIInputHandler::mouseReleased(const OIS::MouseEvent &e, OIS::MouseButton id)
-  //{
-    ////CEGUI::System::getSingleton().injectMouseButtonUp(convertOISMouseButtonToCegui(id));
-  //  return true;
-  //}
-
-}
Index: code/trunk/src/core/InputHandler.h
===================================================================
--- code/trunk/src/core/InputHandler.h	(revision 1407)
+++ 	(revision )
@@ -1,260 +1,0 @@
-/*
- *   ORXONOX - the hottest 3D action shooter ever to exist
- *                    > www.orxonox.net <
- *
- *
- *   License notice:
- *
- *   This program is free software; you can redistribute it and/or
- *   modify it under the terms of the GNU General Public License
- *   as published by the Free Software Foundation; either version 2
- *   of the License, or (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   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 _InputHandler_H__
-#define _InputHandler_H__
-
-#include "CorePrereqs.h"
-
-#include <string>
-#include <vector>
-
-#include "ois/OIS.h"
-#include "util/Math.h"
-#include "OrxonoxClass.h"
-#include "CommandExecutor.h"
-#include "InputInterfaces.h"
-
-namespace orxonox
-{
-  class _CoreExport BaseCommand
-  {
-  public:
-    virtual ~BaseCommand() { }
-    virtual bool execute(float abs = 1.0f, float rel = 1.0f) = 0;
-  };
-
-  class _CoreExport BufferedParamCommand
-  {
-  public:
-    BufferedParamCommand() : value_(0.0f), nValuesAdded_(0), paramIndex_(-1) { }
-    bool execute();
-
-    float value_;
-    unsigned int nValuesAdded_;
-    int paramIndex_;
-    CommandEvaluation evaluation_;
-  };
-
-  class _CoreExport SimpleCommand : public BaseCommand
-  {
-  public:
-    bool execute(float abs = 1.0f, float rel = 1.0f);
-
-    CommandEvaluation evaluation_;
-  };
-
-  class _CoreExport ParamCommand : public BaseCommand
-  {
-  public:
-    ParamCommand() : bRelative_(false), paramModifier_(1.0f), paramCommand_(0) { }
-    bool execute(float abs = 1.0f, float rel = 1.0f);
-
-    bool bRelative_;
-    float paramModifier_;
-    BufferedParamCommand* paramCommand_;
-  };
-
-  class _CoreExport Button
-  {
-  public:
-    Button() { nCommands_[0]=0; nCommands_[1]=0; nCommands_[2]=0; clear(); }
-    virtual ~Button() { clear(); }
-    virtual void clear();
-    virtual bool addParamCommand(ParamCommand* command) { return false; }
-    void parse(std::vector<BufferedParamCommand*>& paramCommandBuffer);
-    bool execute(KeybindMode::Enum 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_;
-    //! 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_;
-  };
-
-
-  class _CoreExport HalfAxis : public Button
-  {
-  public:
-    HalfAxis() : relVal_(0.0f), absVal_(0.0f), paramCommands_(0), nParamCommands_(0),
-                 wasDown_(false), hasChanged_(false) { }
-    using Button::execute;
-    bool execute();
-    //bool execute(KeybindMode::Enum mode) { return Button::execute(mode); }
-    bool addParamCommand(ParamCommand* command);
-    void clear();
-
-    // axis related
-    float relVal_;
-    float absVal_;
-    ParamCommand** paramCommands_;
-    unsigned int nParamCommands_;
-
-    // button related
-    bool wasDown_;
-    bool hasChanged_;
-  };
-
-
-  /**
-    @brief Handles mouse, keyboard and joy stick input while in the actual game mode.
-           Manages the key bindings.
-  */
-  class _CoreExport KeyBinder : public KeyHandler, public MouseHandler, public JoyStickHandler, public OrxonoxClass
-  {
-  public:
-    KeyBinder ();
-    ~KeyBinder();
-
-    void loadBindings();
-    void clearBindings(bool bInit = false);
-
-    void setConfigValues();
-
-  private: // functions
-    void readTrigger(Button& button);
-
-    //static void clearBundle(KeyBindingBundle& bundle, bool bInit);
-    //static void redimensionBinding(KeyBinding& binding);
-
-    void tick(float dt);
-
-    void keyPressed (const KeyEvent& evt);
-    void keyReleased(const KeyEvent& evt);
-    void keyHeld    (const KeyEvent& evt);
-
-    void mouseButtonPressed (MouseButton::Enum id);
-    void mouseButtonReleased(MouseButton::Enum id);
-    void mouseButtonHeld    (MouseButton::Enum id);
-    void mouseMoved         (IntVector2 abs, IntVector2 rel, IntVector2 clippingSize);
-    void mouseScrolled      (int abs, int rel);
-
-    void joyStickButtonPressed (int joyStickID, int button);
-    void joyStickButtonReleased(int joyStickID, int button);
-    void joyStickButtonHeld    (int joyStickID, int button);
-    void joyStickAxisMoved     (int joyStickID, int axis, int value);
-
-  private: // variables
-    //! denotes the number of different keys there are in OIS.
-    static const unsigned int nKeys_s = 0xEE;
-    //! Actual key bindings as bundle for Press, Hold and Release
-    Button keys_ [nKeys_s];
-
-    //! denotes the number of different mouse buttons there are in OIS.
-    static const unsigned int nMouseButtons_s = 8 + 2*2; // 8 buttons and 2 scroll wheels
-    //! Actual key bindings as bundle for Press, Hold and Release
-    Button mouseButtons_ [nMouseButtons_s];
-
-    //! denotes the number of different joy stick buttons there are in OIS.
-    static const unsigned int nJoyStickButtons_s = 32 + 4 * 4; // 32 buttons and 4 POVs with 4 buttons
-    //! Actual key bindings as bundle for Press, Hold and Release
-    Button joyStickButtons_ [nJoyStickButtons_s];
-
-    //! denotes the number of half axes (every axis twice) there can be.
-    static const unsigned int nHalfAxes_s = 56;
-    /**
-    * Array with all the half axes for mouse and joy sticks.
-    * Keep in mind that the positions are fixed and that the first entry is the
-    * positive one and the second is negative.
-    * Sequence is as follows:
-    *  0 -  3: Mouse x and y
-    *  4 -  7: empty
-    *  8 - 23: joy stick (slider) axes 1 to 8
-    * 24 - 55: joy stick axes 1 - 16
-    */
-    HalfAxis halfAxes_[nHalfAxes_s];
-
-    /**
-    * Commands that have additional parameters (axes) are executed at the end of
-    * the tick() so that all values can be buffered for single execution.
-    */
-    std::vector<BufferedParamCommand*> paramCommandBuffer_;
-
-    //! Keeps track of the absolute mouse value (incl. scroll wheel)
-    int mousePosition_[3];
-    //! Used to derive mouse input if requested
-    int mouseRelative_[2];
-    float deriveTime_;
-
-    //##### ConfigValues #####
-    //! 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_;
-  };
-
-
-  /**
-    @brief Captures mouse and keyboard input and distributes it to the
-    GUI.
-  */
-  //class _CoreExport GUIInputHandler : public KeyHandler, public MouseHandler, public JoyStickHandler
-  //{
-  //public:
-  //  GUIInputHandler ();
-  //  ~GUIInputHandler();
-
-  //private:
-  //  // input events
-    //bool keyPressed   (const OIS::KeyEvent   &arg);
-    //bool keyReleased  (const OIS::KeyEvent   &arg);
-    //bool keyHeld      (const OIS::KeyEvent   &arg);
-
-  //  bool mousePressed (const OIS::MouseEvent &arg, OIS::MouseButton id);
-    //bool mouseReleased(const OIS::MouseEvent &arg, OIS::MouseButton id);
-    //bool mouseHeld    (const OIS::MouseEvent &arg, OIS::MouseButton id);
-  //  bool mouseMoved   (const OIS::MouseEvent &arg);
-
-    //bool buttonPressed (const OIS::JoyStickEvent &arg, int button);
-    //bool buttonReleased(const OIS::JoyStickEvent &arg, int button);
-    //bool buttonHeld    (const OIS::JoyStickEvent &arg, int button);
-    //bool axisMoved     (const OIS::JoyStickEvent &arg, int axis);
-    //bool sliderMoved   (const OIS::JoyStickEvent &arg, int id);
-    //bool povMoved      (const OIS::JoyStickEvent &arg, int id);
-  //};
-
-}
-
-#endif /* _InputHandler_H__ */
Index: code/trunk/src/core/InputInterfaces.h
===================================================================
--- code/trunk/src/core/InputInterfaces.h	(revision 1407)
+++ code/trunk/src/core/InputInterfaces.h	(revision 1502)
@@ -254,4 +254,16 @@
 		std::vector<Vector3> mVectors;
   };*/
+  
+  /**
+  * Helper struct to determine which handlers of an object (can implement
+  * multiple handlers) are active.
+  */
+  struct HandlerState
+  {
+    HandlerState() : key(false), mouse(false), joyStick(false) { }
+    bool key;
+    bool mouse;
+    bool joyStick;
+  };
 
   class _CoreExport InputTickable
@@ -259,5 +271,5 @@
   public:
     virtual ~InputTickable() { }
-    virtual void tick(float dt) = 0;
+    virtual void tickInput(float dt, const HandlerState& state) = 0;
   };
 
@@ -272,4 +284,5 @@
     virtual void keyReleased(const KeyEvent& evt) = 0;
     virtual void keyHeld    (const KeyEvent& evt) = 0;
+    //virtual void tickKey    (float dt) { }
   };
 
@@ -286,4 +299,5 @@
     virtual void mouseMoved         (IntVector2 abs, IntVector2 rel, IntVector2 clippingSize) = 0;
     virtual void mouseScrolled      (int abs, int rel)     = 0;
+    //virtual void tickMouse          (float dt) { }
   };
 
@@ -299,6 +313,7 @@
     virtual void joyStickButtonReleased(int joyStickID, int button) = 0;
     virtual void joyStickButtonHeld    (int joyStickID, int button) = 0;
-    virtual void joyStickAxisMoved     (int joyStickID, int axis, int value) = 0;
+    virtual void joyStickAxisMoved     (int joyStickID, int axis, float value) = 0;
     //virtual bool joyStickVector3Moved  (int joyStickID, int index /*, fill list*/) {return true;}
+    //virtual void tickJoyStick          (float dt) { }
   };
 
Index: code/trunk/src/core/InputManager.cc
===================================================================
--- code/trunk/src/core/InputManager.cc	(revision 1407)
+++ code/trunk/src/core/InputManager.cc	(revision 1502)
@@ -34,11 +34,20 @@
 
 #include "InputManager.h"
+#include "util/Convert.h"
 #include "CoreIncludes.h"
+#include "ConfigValueIncludes.h"
 #include "Debug.h"
 #include "InputBuffer.h"
-#include "InputHandler.h"
+#include "KeyBinder.h"
+#include "CommandExecutor.h"
+#include "ConsoleCommand.h"
+#include "Shell.h"
 
 namespace orxonox
 {
+  SetConsoleCommandShortcut(InputManager, keyBind);
+  SetConsoleCommandShortcut(InputManager, storeKeyStroke);
+  SetConsoleCommandShortcut(InputManager, calibrate);
+
   // ###############################
   // ###    Internal Methods     ###
@@ -53,5 +62,6 @@
       inputSystem_(0), keyboard_(0), mouse_(0),
       joySticksSize_(0),
-      state_(IS_UNINIT), stateRequest_(IS_UNINIT),
+      keyBinder_(0), keyDetector_(0), buffer_(0), calibratorCallback_(0),
+      state_(IS_UNINIT), stateRequest_(IS_UNINIT), savedState_(IS_UNINIT),
       keyboardModifiers_(0)
   {
@@ -129,7 +139,4 @@
       if (mouse_)
       {
-        //// hack the mouse position
-        //((OIS::MouseState&)mouse_->getMouseState()).X.abs = windowWidth/2;
-        //((OIS::MouseState&)mouse_->getMouseState()).Y.abs = windowHeight/2;
         setWindowExtents(windowWidth, windowHeight);
       }
@@ -137,4 +144,28 @@
       state_ = IS_NONE;
       CCOUT(ORX_DEBUG) << "Initialising OIS components done." << std::endl;
+
+      // InputManager holds the input buffer --> create one and add it.
+      buffer_ = new InputBuffer();
+      addKeyHandler(buffer_, "buffer");
+      Shell::getInstance().setInputBuffer(buffer_);
+
+      keyBinder_ = new KeyBinder();
+      keyBinder_->loadBindings();
+      addKeyHandler(keyBinder_, "keybinder");
+      addMouseHandler(keyBinder_, "keybinder");
+      addJoyStickHandler(keyBinder_, "keybinder");
+
+      keyDetector_ = new KeyDetector();
+      keyDetector_->loadBindings();
+      addKeyHandler(keyDetector_, "keydetector");
+      addMouseHandler(keyDetector_, "keydetector");
+      addJoyStickHandler(keyDetector_, "keydetector");
+
+      calibratorCallback_ = new CalibratorCallback();
+      addKeyHandler(calibratorCallback_, "calibratorcallback");
+
+      setConfigValues();
+
+      CCOUT(ORX_DEBUG) << "Initialising complete." << std::endl;
     }
     else
@@ -142,19 +173,4 @@
       CCOUT(ORX_WARNING) << "Warning: OIS compoments already initialised, skipping" << std::endl;
     }
-
-    // InputManager holds the input buffer --> create one and add it.
-    addKeyHandler(new InputBuffer(), "buffer");
-
-    KeyBinder* binder = new KeyBinder();
-    binder->loadBindings();
-    addKeyHandler(binder, "keybinder");
-    addMouseHandler(binder, "keybinder");
-    addJoyStickHandler(binder, "keybinder");
-
-    // Read all the key bindings and assign them
-    //if (!_loadBindings())
-    //  return false;
-
-    CCOUT(ORX_DEBUG) << "Initialising complete." << std::endl;
     return true;
   }
@@ -216,5 +232,5 @@
         // register our listener in OIS.
         mouse_->setEventCallback(this);
-        CCOUT(ORX_DEBUG) << "Created OIS keyboard" << std::endl;
+        CCOUT(ORX_DEBUG) << "Created OIS mouse" << std::endl;
         return true;
       }
@@ -276,8 +292,73 @@
     povStates_.resize(joySticksSize_);
     sliderStates_.resize(joySticksSize_);
+    joySticksCalibration_.resize(joySticksSize_);
+    for (unsigned int iJoyStick = 0; iJoyStick < joySticksSize_; iJoyStick++)
+    {
+      // reset the calibration with default values
+      for (unsigned int i = 0; i < 24; i++)
+      {
+        joySticksCalibration_[iJoyStick].negativeCoeff[i] = 1.0f/32767.0f;
+        joySticksCalibration_[iJoyStick].positiveCoeff[i] = 1.0f/32768.0f;
+        joySticksCalibration_[iJoyStick].zeroStates[i] = 0;
+      }
+    }
     return success;
   }
 
   /**
+    @brief Sets the configurable values. Use keybindings.ini as file..
+  */
+  void InputManager::setConfigValues()
+  {
+    if (joySticksSize_)
+    {
+      std::vector<MultiTypeMath> coeffPos;
+      std::vector<MultiTypeMath> coeffNeg;
+      std::vector<MultiTypeMath> zero;
+      coeffPos.resize(24);
+      coeffNeg.resize(24);
+      zero.resize(24);
+      for (unsigned int i = 0; i < 24; i++)
+      {
+        coeffPos[i] =  1.0f/32767.0f;
+        coeffNeg[i] =  1.0f/32768.0f;
+        zero[i]     =  0;
+      }
+
+      ConfigValueContainer* cont = getIdentifier()->getConfigValueContainer("CoeffPos");
+      if (!cont)
+      {
+          cont = new ConfigValueContainer(CFT_Keybindings, getIdentifier(), "CoeffPos", coeffPos);
+          getIdentifier()->addConfigValueContainer("CoeffPos", cont);
+      }
+      cont->getValue(&coeffPos);
+
+      cont = getIdentifier()->getConfigValueContainer("CoeffNeg");
+      if (!cont)
+      {
+          cont = new ConfigValueContainer(CFT_Keybindings, getIdentifier(), "CoeffNeg", coeffNeg);
+          getIdentifier()->addConfigValueContainer("CoeffNeg", cont);
+      }
+      cont->getValue(&coeffNeg);
+
+      cont = getIdentifier()->getConfigValueContainer("Zero");
+      if (!cont)
+      {
+          cont = new ConfigValueContainer(CFT_Keybindings, getIdentifier(), "Zero", zero);
+          getIdentifier()->addConfigValueContainer("Zero", cont);
+      }
+      cont->getValue(&zero);
+
+      // copy values to our own variables
+      for (unsigned int i = 0; i < 24; i++)
+      {
+        joySticksCalibration_[0].positiveCoeff[i] = coeffPos[i];
+        joySticksCalibration_[0].negativeCoeff[i] = coeffNeg[i];
+        joySticksCalibration_[0].zeroStates[i]    = zero[i];
+      }
+    }
+  }
+
+  /**
     @brief Destroys all the created input devices and sets the InputManager to construction state.
   */
@@ -288,9 +369,15 @@
       CCOUT(ORX_DEBUG) << "Destroying ..." << std::endl;
 
-      if (keyHandlers_.find("buffer") != keyHandlers_.end())
-        delete keyHandlers_["buffer"];
-
-      if (keyHandlers_.find("keybinder") != keyHandlers_.end())
-        delete keyHandlers_["keybinder"];
+      if (buffer_)
+        delete buffer_;
+
+      if (keyBinder_)
+        delete keyBinder_;
+
+      if (keyDetector_)
+        delete keyDetector_;
+
+      if (calibratorCallback_)
+        delete calibratorCallback_;
 
       keyHandlers_.clear();
@@ -301,4 +388,6 @@
       _destroyMouse();
       _destroyJoySticks();
+
+      activeHandlers_.clear();
 
       // inputSystem_ can never be 0, or else the code is mistaken
@@ -355,24 +444,44 @@
       activeJoyStickHandlers_.clear();
       joyStickButtonsDown_.clear();
+      povStates_.clear();
+      sliderStates_.clear();
+      joySticksCalibration_.clear();
     }
     CCOUT(ORX_DEBUG) << "Joy sticks destroyed." << std::endl;
   }
 
+  void InputManager::_saveState()
+  {
+    savedHandlers_.activeHandlers_ = activeHandlers_;
+    savedHandlers_.activeJoyStickHandlers_ = activeJoyStickHandlers_;
+    savedHandlers_.activeKeyHandlers_ = activeKeyHandlers_;
+    savedHandlers_.activeMouseHandlers_ = activeMouseHandlers_;
+  }
+
+  void InputManager::_restoreState()
+  {
+    activeHandlers_ = savedHandlers_.activeHandlers_;
+    activeJoyStickHandlers_ = savedHandlers_.activeJoyStickHandlers_;
+    activeKeyHandlers_ = savedHandlers_.activeKeyHandlers_;
+    activeMouseHandlers_ = savedHandlers_.activeMouseHandlers_;
+  }
+
   void InputManager::_updateTickables()
   {
-    // we can use a set to have a list of unique pointers (an object can implement all 3 handlers)
-    std::set<InputTickable*> tempSet;
+    // we can use a map to have a list of unique pointers (an object can implement all 3 handlers)
+    std::map<InputTickable*, HandlerState> tempSet;
     for (unsigned int iHandler = 0; iHandler < activeKeyHandlers_.size(); iHandler++)
-      tempSet.insert(activeKeyHandlers_[iHandler]);
+      tempSet[activeKeyHandlers_[iHandler]].joyStick = true;
     for (unsigned int iHandler = 0; iHandler < activeMouseHandlers_.size(); iHandler++)
-      tempSet.insert(activeMouseHandlers_[iHandler]);
+      tempSet[activeMouseHandlers_[iHandler]].mouse = true;
     for (unsigned int iJoyStick  = 0; iJoyStick < joySticksSize_; iJoyStick++)
       for (unsigned int iHandler = 0; iHandler  < activeJoyStickHandlers_[iJoyStick].size(); iHandler++)
-        tempSet.insert(activeJoyStickHandlers_[iJoyStick][iHandler]);
-
-    // copy the content of the set back to the actual vector
+        tempSet[activeJoyStickHandlers_[iJoyStick][iHandler]].joyStick = true;
+
+    // copy the content of the map back to the actual vector
     activeHandlers_.clear();
-    for (std::set<InputTickable*>::const_iterator itHandler = tempSet.begin(); itHandler != tempSet.end(); itHandler++)
-      activeHandlers_.push_back(*itHandler);
+    for (std::map<InputTickable*, HandlerState>::const_iterator itHandler = tempSet.begin();
+        itHandler != tempSet.end(); itHandler++)
+      activeHandlers_.push_back(std::pair<InputTickable*, HandlerState>((*itHandler).first, (*itHandler).second));
   }
 
@@ -392,9 +501,10 @@
       return;
 
-    // reset the game if it has changed
     if (state_ != stateRequest_)
     {
-      if (stateRequest_ != IS_CUSTOM)
-      {
+      InputState sr = stateRequest_;
+      switch (sr)
+      {
+      case IS_NORMAL:
         activeKeyHandlers_.clear();
         activeMouseHandlers_.clear();
@@ -402,30 +512,104 @@
           activeJoyStickHandlers_[i].clear();
 
-        switch (stateRequest_)
+        // normal play mode
+        // note: we assume that the handlers exist since otherwise, something's wrong anyway.
+        enableKeyHandler("keybinder");
+        enableMouseHandler("keybinder");
+        enableJoyStickHandler("keybinder", 0);
+        stateRequest_ = IS_NORMAL;
+        state_ = IS_NORMAL;
+        break;
+
+      case IS_GUI:
+        state_ = IS_GUI;
+        break;
+
+      case IS_CONSOLE:
+        activeKeyHandlers_.clear();
+        activeMouseHandlers_.clear();
+        for (unsigned int i = 0; i < joySticksSize_; i++)
+          activeJoyStickHandlers_[i].clear();
+
+        enableMouseHandler("keybinder");
+        enableJoyStickHandler("keybinder", 0);
+        enableKeyHandler("buffer");
+        stateRequest_ = IS_CONSOLE;
+        state_ = IS_CONSOLE;
+        break;
+
+      case IS_DETECT:
+        savedState_ = state_;
+        _saveState();
+
+        activeKeyHandlers_.clear();
+        activeMouseHandlers_.clear();
+        for (unsigned int i = 0; i < joySticksSize_; i++)
+          activeJoyStickHandlers_[i].clear();
+
+        enableKeyHandler("keydetector");
+        enableMouseHandler("keydetector");
+        enableJoyStickHandler("keydetector", 0);
+
+        stateRequest_ = IS_DETECT;
+        state_ = IS_DETECT;
+        break;
+
+      case IS_NODETECT:
+        _restoreState();
+        keysDown_.clear();
+        mouseButtonsDown_.clear();
+        joyStickButtonsDown_[0].clear();
+        state_ = IS_NODETECT;
+        stateRequest_ = savedState_;
+        break;
+
+      case IS_CALIBRATE:
+        if (joySticksSize_)
         {
-        case IS_NORMAL:
-          // normal play mode
-          // note: we assume that the handlers exist since otherwise, something's wrong anyway.
-          enableKeyHandler("keybinder");
-          enableMouseHandler("keybinder");
-          enableMouseHandler("SpaceShip");
-          enableJoyStickHandler("keybinder", 0);
-          break;
-
-        case IS_GUI:
-          // TODO: do stuff
-          break;
-
-        case IS_CONSOLE:
-          enableMouseHandler("keybinder");
-          enableMouseHandler("SpaceShip");
-          enableJoyStickHandler("keybinder", 0);
-          enableKeyHandler("buffer");
-          break;
-
-        default:
-          break;
+          savedState_ = _getSingleton().state_;
+          for (unsigned int i = 0; i < 24; i++)
+          {
+            marginalsMax_[i] = INT_MIN;
+            marginalsMin_[i] = INT_MAX;
+          }
+          COUT(0) << "Move all joy stick axes in all directions a few times. "
+            << "Then put all axes in zero state and hit enter." << std::endl;
+
+          savedState_ = state_;
+          _saveState();
+
+          activeKeyHandlers_.clear();
+          activeMouseHandlers_.clear();
+          for (unsigned int i = 0; i < joySticksSize_; i++)
+            activeJoyStickHandlers_[i].clear();
+
+          enableKeyHandler("calibratorcallback");
+          stateRequest_ = IS_CALIBRATE;
+          state_ = IS_CALIBRATE;
         }
-        state_ = stateRequest_;
+        else
+        {
+          COUT(3) << "Connot calibrate, no joy stick found!" << std::endl;
+          stateRequest_ = state_;
+        }
+        break;
+
+      case IS_NOCALIBRATE:
+        _completeCalibration();
+        _restoreState();
+        keyBinder_->resetJoyStickAxes();
+        state_ = IS_NOCALIBRATE;
+        stateRequest_ = savedState_;
+        break;
+
+      case IS_NONE:
+        activeKeyHandlers_.clear();
+        activeMouseHandlers_.clear();
+        for (unsigned int i = 0; i < joySticksSize_; i++)
+          activeJoyStickHandlers_[i].clear();
+        state_ = IS_NONE;
+
+      default:
+        break;
       }
     }
@@ -439,25 +623,79 @@
       joySticks_[i]->capture();
 
-
-    // call all the handlers for the held key events
-    for (unsigned int iKey = 0; iKey < keysDown_.size(); iKey++)
-      for (unsigned int iHandler = 0; iHandler < activeKeyHandlers_.size(); iHandler++)
-        activeKeyHandlers_[iHandler]->keyHeld(KeyEvent(keysDown_[iKey], keyboardModifiers_));
-
-    // call all the handlers for the held mouse button events
-    for (unsigned int iButton = 0; iButton < mouseButtonsDown_.size(); iButton++)
-      for (unsigned int iHandler = 0; iHandler < activeMouseHandlers_.size(); iHandler++)
-        activeMouseHandlers_[iHandler]->mouseButtonHeld(mouseButtonsDown_[iButton]);
-
-    // call all the handlers for the held joy stick button events
-    for (unsigned int iJoyStick  = 0; iJoyStick < joySticksSize_; iJoyStick++)
-      for (unsigned int iButton   = 0; iButton   < joyStickButtonsDown_[iJoyStick].size(); iButton++)
-        for (unsigned int iHandler = 0; iHandler  < activeJoyStickHandlers_[iJoyStick].size(); iHandler++)
-          activeJoyStickHandlers_[iJoyStick][iHandler]->joyStickButtonHeld(iJoyStick, joyStickButtonsDown_[iJoyStick][iButton]);
-
-
-    // call the ticks
+    if (state_ != IS_CALIBRATE)
+    {
+      // call all the handlers for the held key events
+      for (unsigned int iKey = 0; iKey < keysDown_.size(); iKey++)
+        for (unsigned int iHandler = 0; iHandler < activeKeyHandlers_.size(); iHandler++)
+          activeKeyHandlers_[iHandler]->keyHeld(KeyEvent(keysDown_[iKey], keyboardModifiers_));
+
+      // call all the handlers for the held mouse button events
+      for (unsigned int iButton = 0; iButton < mouseButtonsDown_.size(); iButton++)
+        for (unsigned int iHandler = 0; iHandler < activeMouseHandlers_.size(); iHandler++)
+          activeMouseHandlers_[iHandler]->mouseButtonHeld(mouseButtonsDown_[iButton]);
+
+      // call all the handlers for the held joy stick button events
+      for (unsigned int iJoyStick  = 0; iJoyStick < joySticksSize_; iJoyStick++)
+        for (unsigned int iButton   = 0; iButton   < joyStickButtonsDown_[iJoyStick].size(); iButton++)
+          for (unsigned int iHandler = 0; iHandler  < activeJoyStickHandlers_[iJoyStick].size(); iHandler++)
+            activeJoyStickHandlers_[iJoyStick][iHandler]->joyStickButtonHeld(iJoyStick, joyStickButtonsDown_[iJoyStick][iButton]);
+    }
+
+    // call the ticks for the handlers (need to be treated specially)
     for (unsigned int iHandler = 0; iHandler < activeHandlers_.size(); iHandler++)
-      activeHandlers_[iHandler]->tick(dt);
+      activeHandlers_[iHandler].first->tickInput(dt, activeHandlers_[iHandler].second);
+  }
+
+  void InputManager::_completeCalibration()
+  {
+    for (unsigned int i = 0; i < 24; i++)
+    {
+      // positive coefficient
+      if (marginalsMax_[i] == INT_MIN)
+        marginalsMax_[i] =  32767;
+      // coefficients
+      if (marginalsMax_[i] - joySticksCalibration_[0].zeroStates[i])
+        joySticksCalibration_[0].positiveCoeff[i] =  1.0f/(marginalsMax_[i] - joySticksCalibration_[0].zeroStates[i]);
+      else
+        joySticksCalibration_[0].positiveCoeff[i] =  1.0f;
+
+      // config value
+      ConfigValueContainer* cont = getIdentifier()->getConfigValueContainer("CoeffPos");
+      assert(cont);
+      cont->set(i, joySticksCalibration_[0].positiveCoeff[i]);
+
+      // negative coefficient
+      if (marginalsMin_[i] == INT_MAX)
+        marginalsMin_[i] = -32768;
+      // coefficients
+      if (marginalsMin_[i] - joySticksCalibration_[0].zeroStates[i])
+        joySticksCalibration_[0].negativeCoeff[i] = -1.0f/(marginalsMin_[i] - joySticksCalibration_[0].zeroStates[i]);
+      else
+        joySticksCalibration_[0].negativeCoeff[i] =  1.0f;
+      // config value
+      cont = getIdentifier()->getConfigValueContainer("CoeffNeg");
+      assert(cont);
+      cont->set(i, joySticksCalibration_[0].negativeCoeff[i]);
+
+      // zero states
+      if (i < 8)
+      {
+        if (!(i & 1))
+          joySticksCalibration_[0].zeroStates[i] = joySticks_[0]->getJoyStickState().mSliders[i/2].abX;
+        else
+          joySticksCalibration_[0].zeroStates[i] = joySticks_[0]->getJoyStickState().mSliders[i/2].abY;
+      }
+      else
+      {
+        if (i - 8 < joySticks_[0]->getJoyStickState().mAxes.size())
+          joySticksCalibration_[0].zeroStates[i] = joySticks_[0]->getJoyStickState().mAxes[i - 8].abs;
+        else
+          joySticksCalibration_[0].zeroStates[i] = 0;
+      }
+      // config value
+      cont = getIdentifier()->getConfigValueContainer("Zero");
+      assert(cont);
+      cont->set(i, joySticksCalibration_[0].zeroStates[i]);
+    }
   }
 
@@ -594,5 +832,5 @@
   // ###### Joy Stick Events ######
 
-  bool InputManager::buttonPressed(const OIS::JoyStickEvent &arg, int button)
+  inline unsigned int InputManager::_getJoystick(const OIS::JoyStickEvent& arg)
   {
     // use the device to identify which one called the method
@@ -600,8 +838,21 @@
     unsigned int iJoyStick = 0;
     while (joySticks_[iJoyStick] != joyStick)
+    {
       iJoyStick++;
+      if (iJoyStick == joySticksSize_)
+      {
+        CCOUT(3) << "Unknown joystick fired an event. This means there is a bug somewhere! Aborting." << std::endl;
+        abort();
+      }
+    }
+    return iJoyStick;
+  }
+
+  bool InputManager::buttonPressed(const OIS::JoyStickEvent &arg, int button)
+  {
+    unsigned int iJoyStick = _getJoystick(arg);
 
     // check whether the button already is in the list (can happen when focus was lost)
-    std::vector<int> buttonsDown = joyStickButtonsDown_[iJoyStick];
+    std::vector<int>& buttonsDown = joyStickButtonsDown_[iJoyStick];
     unsigned int iButton = 0;
     while (iButton < buttonsDown.size() && buttonsDown[iButton] != button)
@@ -618,12 +869,8 @@
   bool InputManager::buttonReleased(const OIS::JoyStickEvent &arg, int button)
   {
-    // use the device to identify which one called the method
-    OIS::JoyStick* joyStick = (OIS::JoyStick*)arg.device;
-    unsigned int iJoyStick = 0;
-    while (joySticks_[iJoyStick] != joyStick)
-      iJoyStick++;
+    unsigned int iJoyStick = _getJoystick(arg);
 
     // remove the button from the joyStickButtonsDown_ list
-    std::vector<int> buttonsDown = joyStickButtonsDown_[iJoyStick];
+    std::vector<int>& buttonsDown = joyStickButtonsDown_[iJoyStick];
     for (unsigned int iButton = 0; iButton < buttonsDown.size(); iButton++)
     {
@@ -641,16 +888,35 @@
   }
 
+  void InputManager::_fireAxis(unsigned int iJoyStick, int axis, int value)
+  {
+    if (state_ == IS_CALIBRATE)
+    {
+      if (value > marginalsMax_[axis])
+        marginalsMax_[axis] = value;
+      if (value < marginalsMin_[axis])
+        marginalsMin_[axis] = value;
+    }
+    else
+    {
+      float fValue = value - joySticksCalibration_[iJoyStick].zeroStates[axis];
+      if (fValue > 0.0f)
+        fValue *= joySticksCalibration_[iJoyStick].positiveCoeff[axis];
+      else
+        fValue *= joySticksCalibration_[iJoyStick].negativeCoeff[axis];
+
+      for (unsigned int iHandler = 0; iHandler < activeJoyStickHandlers_[iJoyStick].size(); iHandler++)
+        activeJoyStickHandlers_[iJoyStick][iHandler]->joyStickAxisMoved(iJoyStick, axis, fValue);
+    }
+  }
+
   bool InputManager::axisMoved(const OIS::JoyStickEvent &arg, int axis)
   {
-    //CCOUT(3) << arg.state.mAxes[axis].abs << std::endl;
-    // use the device to identify which one called the method
-    OIS::JoyStick* joyStick = (OIS::JoyStick*)arg.device;
-    unsigned int iJoyStick = 0;
-    while (joySticks_[iJoyStick] != joyStick)
-      iJoyStick++;
+    //if (arg.state.mAxes[axis].abs > 10000 || arg.state.mAxes[axis].abs < -10000)
+    //{ CCOUT(3) << "axis " << axis << " moved" << arg.state.mAxes[axis].abs << std::endl;}
+
+    unsigned int iJoyStick = _getJoystick(arg);
 
     // keep in mind that the first 8 axes are reserved for the sliders
-    for (unsigned int iHandler = 0; iHandler < activeJoyStickHandlers_[iJoyStick].size(); iHandler++)
-      activeJoyStickHandlers_[iJoyStick][iHandler]->joyStickAxisMoved(iJoyStick, axis + 8, arg.state.mAxes[axis].abs);
+    _fireAxis(iJoyStick, axis + 8, arg.state.mAxes[axis].abs);
 
     return true;
@@ -659,25 +925,14 @@
   bool InputManager::sliderMoved(const OIS::JoyStickEvent &arg, int id)
   {
+    //if (arg.state.mSliders[id].abX > 10000 || arg.state.mSliders[id].abX < -10000)
+    //{CCOUT(3) << "slider " << id << " moved" << arg.state.mSliders[id].abX << std::endl;}
     //CCOUT(3) << arg.state.mSliders[id].abX << "\t |" << arg.state.mSliders[id].abY << std::endl;
-    // use the device to identify which one called the method
-    OIS::JoyStick* joyStick = (OIS::JoyStick*)arg.device;
-    unsigned int iJoyStick = 0;
-    while (joySticks_[iJoyStick] != joyStick)
-      iJoyStick++;
+
+    unsigned int iJoyStick = _getJoystick(arg);
 
     if (sliderStates_[iJoyStick].sliderStates[id].x != arg.state.mSliders[id].abX)
-    {
-      // slider X axis changed
-      sliderStates_[iJoyStick].sliderStates[id].x = arg.state.mSliders[id].abX;
-      for (unsigned int iHandler = 0; iHandler < activeJoyStickHandlers_[iJoyStick].size(); iHandler++)
-        activeJoyStickHandlers_[iJoyStick][iHandler]->joyStickAxisMoved(iJoyStick, id * 2, arg.state.mSliders[id].abX);
-    }
+      _fireAxis(iJoyStick, id * 2, arg.state.mSliders[id].abX);
     else if (sliderStates_[iJoyStick].sliderStates[id].y != arg.state.mSliders[id].abY)
-    {
-      // slider Y axis changed
-      sliderStates_[iJoyStick].sliderStates[id].y = arg.state.mSliders[id].abY;
-      for (unsigned int iHandler = 0; iHandler < activeJoyStickHandlers_[iJoyStick].size(); iHandler++)
-        activeJoyStickHandlers_[iJoyStick][iHandler]->joyStickAxisMoved(iJoyStick, id * 2 + 1, arg.state.mSliders[id].abY);
-    }
+      _fireAxis(iJoyStick, id * 2 + 1, arg.state.mSliders[id].abY);
 
     return true;
@@ -686,9 +941,5 @@
   bool InputManager::povMoved(const OIS::JoyStickEvent &arg, int id)
   {
-    // use the device to identify which one called the method
-    OIS::JoyStick* joyStick = (OIS::JoyStick*)arg.device;
-    unsigned int iJoyStick = 0;
-    while (joySticks_[iJoyStick] != joyStick)
-      iJoyStick++;
+    unsigned int iJoyStick = _getJoystick(arg);
 
     // translate the POV into 8 simple buttons
@@ -702,6 +953,7 @@
     if (lastState & OIS::Pov::West)
       buttonReleased(arg, 32 + id * 4 + 3);
-    
+
     povStates_[iJoyStick].povStates[id] = arg.state.mPOV[id].direction;
+
     int currentState = povStates_[iJoyStick][id];
     if (currentState & OIS::Pov::North)
@@ -719,9 +971,5 @@
   /*bool InputManager::vector3Moved(const OIS::JoyStickEvent &arg, int id)
   {
-    // use the device to identify which one called the method
-    OIS::JoyStick* joyStick = (OIS::JoyStick*)arg.device;
-    unsigned int iJoyStick = 0;
-    while (joySticks_[iJoyStick] != joyStick)
-      iJoyStick++;
+    unsigned int iJoyStick = _getJoystick(arg);
 
     for (unsigned int iHandler = 0; iHandler < activeJoyStickHandlers_[iJoyStick].size(); iHandler++)
@@ -737,4 +985,6 @@
   // ################################
 
+  std::string InputManager::bindingCommmandString_s = "";
+
   bool InputManager::initialise(const size_t windowHnd, int windowWidth, int windowHeight,
     bool createKeyboard, bool createMouse, bool createJoySticks)
@@ -780,5 +1030,5 @@
   }
 
-  bool InputManager::isKeyDown(KeyCode::Enum key)
+  /*bool InputManager::isKeyDown(KeyCode::Enum key)
   {
     if (_getSingleton().keyboard_)
@@ -786,7 +1036,7 @@
     else
       return false;
-  }
-
-  bool InputManager::isModifierDown(KeyboardModifier::Enum modifier)
+  }*/
+
+  /*bool InputManager::isModifierDown(KeyboardModifier::Enum modifier)
   {
     if (_getSingleton().keyboard_)
@@ -794,5 +1044,5 @@
     else
       return false;
-  }
+  }*/
 
   /*const MouseState InputManager::getMouseState()
@@ -811,5 +1061,4 @@
       return JoyStickState();
   }*/
-
 
   void InputManager::destroy()
@@ -870,4 +1119,22 @@
   }
 
+  void InputManager::storeKeyStroke(const std::string& name)
+  {
+    setInputState(IS_NODETECT);
+    COUT(0) << "Binding string \"" << bindingCommmandString_s << "\" on key '" << name << "'" << std::endl;
+    CommandExecutor::execute("config KeyBinder " + name + " " + bindingCommmandString_s, false);
+  }
+
+  void InputManager::keyBind(const std::string& command)
+  {
+    bindingCommmandString_s = command;
+    setInputState(IS_DETECT);
+    COUT(0) << "Press any button/key or move a mouse/joystick axis" << std::endl;
+  }
+
+  void InputManager::calibrate()
+  {
+    _getSingleton().setInputState(IS_CALIBRATE);
+  }
 
   // ###### KeyHandler ######
Index: code/trunk/src/core/InputManager.h
===================================================================
--- code/trunk/src/core/InputManager.h	(revision 1407)
+++ code/trunk/src/core/InputManager.h	(revision 1502)
@@ -65,4 +65,22 @@
   public:
     IntVector2 sliderStates[4];
+  };
+
+  /**
+  * Struct for storing a custom input state
+  */
+  struct StoredState
+  {
+    std::vector<KeyHandler*>                    activeKeyHandlers_;
+    std::vector<MouseHandler*>                  activeMouseHandlers_;
+    std::vector<std::vector<JoyStickHandler*> > activeJoyStickHandlers_;
+    std::vector<std::pair<InputTickable*, HandlerState> > activeHandlers_;
+  };
+
+  struct JoyStickCalibration
+  {
+    int zeroStates[24];
+    float positiveCoeff[24];
+    float negativeCoeff[24];
   };
 
@@ -80,11 +98,18 @@
     enum InputState
     {
-      IS_UNINIT,  //!< InputManager has not yet been initialised.
-      IS_NONE,    //!< Input is discarded.
-      IS_NORMAL,  //!< Normal play state. Key and button bindings are active.
-      IS_GUI,     //!< All OIS input events are passed to CEGUI.
-      IS_CONSOLE, //!< Keyboard input is redirected to the InputBuffer.
-      IS_CUSTOM   //!< Any possible configuration.
+      IS_UNINIT,    //!< InputManager has not yet been initialised.
+      IS_NONE,      //!< Input is discarded.
+      IS_NORMAL,    //!< Normal play state. Key and button bindings are active.
+      IS_GUI,       //!< All OIS input events are passed to CEGUI.
+      IS_CONSOLE,   //!< Keyboard input is redirected to the InputBuffer.
+      IS_DETECT,    //!< All the input additionally goes to the KeyDetector
+      IS_NODETECT,  //!< remove KeyDetector
+      IS_NOCALIBRATE,
+      IS_CALIBRATE,
+      IS_CUSTOM     //!< Any possible configuration.
     };
+
+  public: // member functions
+    void setConfigValues();
 
   public: // static functions
@@ -103,6 +128,6 @@
     static void destroyJoySticks();
 
-    static bool isModifierDown(KeyboardModifier::Enum modifier);
-    static bool isKeyDown(KeyCode::Enum key);
+    //static bool isModifierDown(KeyboardModifier::Enum modifier);
+    //static bool isKeyDown(KeyCode::Enum key);
     //static const MouseState getMouseState();
     //static const JoyStickState getJoyStickState(unsigned int ID);
@@ -112,4 +137,9 @@
     static void setInputState(const InputState state);
     static InputState getInputState();
+
+    static void storeKeyStroke(const std::string& name);
+    static void keyBind(const std::string& command);
+
+    static void calibrate();
 
     static bool addKeyHandler                 (KeyHandler* handler, const std::string& name);
@@ -152,4 +182,12 @@
 
     void _updateTickables();
+
+    void _saveState();
+    void _restoreState();
+
+    void _completeCalibration();
+
+    void _fireAxis(unsigned int iJoyStick, int axis, int value);
+    unsigned int _getJoystick(const OIS::JoyStickEvent& arg);
 
     void tick(float dt);
@@ -172,13 +210,27 @@
 
   private: // variables
-    OIS::InputManager*                          inputSystem_; //!< OIS input manager
-    OIS::Keyboard*                              keyboard_;    //!< OIS mouse
-    OIS::Mouse*                                 mouse_;       //!< OIS keyboard
-    std::vector<OIS::JoyStick*>                 joySticks_;   //!< OIS joy sticks
+    OIS::InputManager*                          inputSystem_;     //!< OIS input manager
+    OIS::Keyboard*                              keyboard_;        //!< OIS mouse
+    OIS::Mouse*                                 mouse_;           //!< OIS keyboard
+    std::vector<OIS::JoyStick*>                 joySticks_;       //!< OIS joy sticks
     unsigned int                                joySticksSize_;
+
+    KeyBinder*                                  keyBinder_;       //!< KeyBinder instance
+    KeyDetector*                                keyDetector_;     //!< KeyDetector instance
+    InputBuffer*                                buffer_;          //!< InputBuffer instance
+    CalibratorCallback*                         calibratorCallback_;
 
     InputState state_;
     InputState stateRequest_;
+    InputState savedState_;
     unsigned int keyboardModifiers_;
+    StoredState savedHandlers_;
+
+    // joystick calibration
+    //std::vector<int> marginalsMaxConfig_;
+    //std::vector<int> marginalsMinConfig_;
+    int marginalsMax_[24];
+    int marginalsMin_[24];
+    bool bCalibrated_;
 
     //! Keeps track of the joy stick POV states
@@ -186,4 +238,5 @@
     //! Keeps track of the possibly two slider axes
     std::vector<SliderStates>                   sliderStates_;
+    std::vector<JoyStickCalibration>            joySticksCalibration_;
 
     std::map<std::string, KeyHandler*>          keyHandlers_;
@@ -194,5 +247,5 @@
     std::vector<MouseHandler*>                  activeMouseHandlers_;
     std::vector<std::vector<JoyStickHandler*> > activeJoyStickHandlers_;
-    std::vector<InputTickable*>                 activeHandlers_;
+    std::vector<std::pair<InputTickable*, HandlerState> > activeHandlers_;
 
     std::vector<Key>                            keysDown_;
@@ -200,4 +253,5 @@
     std::vector<std::vector<int> >              joyStickButtonsDown_;
 
+    static std::string                          bindingCommmandString_s;
   };
 
Index: code/trunk/src/core/Iterator.h
===================================================================
--- code/trunk/src/core/Iterator.h	(revision 1407)
+++ code/trunk/src/core/Iterator.h	(revision 1502)
@@ -50,5 +50,4 @@
 
 #include "ObjectList.h"
-#include "Debug.h"
 
 namespace orxonox
Index: code/trunk/src/core/KeyBinder.cc
===================================================================
--- code/trunk/src/core/KeyBinder.cc	(revision 1502)
+++ code/trunk/src/core/KeyBinder.cc	(revision 1502)
@@ -0,0 +1,908 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   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 "KeyBinder.h"
+#include <fstream>
+#include <limits.h>
+#include "util/Convert.h"
+#include "util/SubString.h"
+#include "util/String.h"
+#include "Debug.h"
+#include "ConfigValueIncludes.h"
+#include "CoreIncludes.h"
+#include "CommandExecutor.h"
+#include "ConsoleCommand.h"
+#include "Executor.h"
+// TODO: only needed by the CalibratorCallback class; move to new file
+#include "InputManager.h"
+
+namespace orxonox
+{
+  // ###############################
+  // ###  BufferedParamCommand   ###
+  // ###############################
+
+  /**
+  * 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 (nValuesAdded_)
+    {
+      BufferedParamCommand& cmd = *this;
+      cmd.evaluation_.setEvaluatedParameter(cmd.paramIndex_, cmd.value_);
+      // reset
+      cmd.nValuesAdded_ = 0;
+      cmd.value_ = 0;
+      return cmd.evaluation_.execute();
+    }
+    else
+      return true;
+  }
+
+  // ###############################
+  // #####    SimpleCommand    #####
+  // ###############################
+
+  /**
+  * Executes a simple command with no additional paramters.
+  * @return True if command execution was successful, false otherwise.
+  */
+  bool SimpleCommand::execute(float abs, float rel)
+  {
+    return evaluation_.execute();
+  }
+
+  // ###############################
+  // #####    ParamCommand     #####
+  // ###############################
+
+  /**
+  * 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 (bRelative_)
+    {
+      if (rel != 0.0f)
+      {
+        // we have to calculate a relative movement.
+        // paramModifier_ says how much one keystroke is
+        cmd.value_ += paramModifier_ * rel;
+      }
+    }
+    else if (abs != 0.0f)
+    {
+      // Usually, joy sticks create 'noise' (they return values if they're in 0 position)
+      // and normally this is caught in tickInput(), but that threshold cannot be to high
+      // in order to preserve accuracy. Instead, we have to catch the problem here. An example:
+      // Someone only uses buttons with an active joystick. The joy stick value could then
+      // be 0.05 for instance and the the key value 1. Without handling the problem, the final
+      // value would be computed to (1+0.05)/2=0.5025 which is not what the user expects.
+      float absQ = abs * abs;
+      float valueQ = cmd.value_ * cmd.value_;
+      if (absQ > 50.0f * valueQ) // ease up comparison by using quadratics
+      {
+        cmd.value_ = abs * paramModifier_;
+        cmd.nValuesAdded_ = 1;
+      }
+      else if (absQ * 50.0f < valueQ)
+      {
+        // abs is too small, we just don't do anything
+      }
+      else
+      {
+        // we have to calculate the absolute position of the axis.
+        // Since there might be another axis that is affected, we have to wait and
+        // store the result in a temporary place
+        cmd.value_ = (cmd.value_ * cmd.nValuesAdded_ + paramModifier_ * abs) / ++cmd.nValuesAdded_;
+      }
+    }
+    return true;
+  }
+
+  // ###############################
+  // #####       Button        #####
+  // ###############################
+
+  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] = 0;
+        nCommands_[j] = 0;
+      }
+      else
+      {
+        commands_[j] = 0;
+      }
+    }
+  }
+
+  void Button::parse(std::vector<BufferedParamCommand*>& paramCommandBuffer)
+  {
+    if (isEmpty(bindingString_))
+    {
+      clear();
+      return;
+    }
+
+    // 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] != "")
+      {
+        SubString tokens(commandStrings[iCommand], " ", SubString::WhiteSpaces, false,
+            '\\', false, '"', false, '(', ')', false, '\0');
+
+        unsigned int iToken = 0;
+
+        // for real axes, we can feed a ButtonThreshold argument as entire command
+        if (getLowercase(tokens[0]) == "buttonthreshold")
+        {
+          if (tokens.size() == 1)
+            continue;
+          // may fail, but doesn't matter
+          convertValue(&buttonThreshold_, tokens[1]);
+          continue;
+        }
+
+        // first argument can be OnPress, OnHold OnRelease or nothing
+        KeybindMode::Enum mode = KeybindMode::None;
+        if (getLowercase(tokens[iToken]) == "onpress")
+          mode = KeybindMode::OnPress,   iToken++;
+        if (getLowercase(tokens[iToken]) == "onrelease")
+          mode = KeybindMode::OnRelease, iToken++;
+        if (getLowercase(tokens[iToken]) == "onhold")
+          mode = KeybindMode::OnHold,    iToken++;
+
+        if (iToken == tokens.size())
+          continue;
+
+        // second argument can be the amplitude for the case it as an axis command
+        // default amplitude is 1.0f
+        float paramModifier = 1.0f;
+        if (getLowercase(tokens[iToken]) == "scale")
+        {
+          iToken++;
+          if (iToken == tokens.size() || !convertValue(&paramModifier, tokens[iToken]))
+          {
+            COUT(2) << "Error while parsing key binding " << name_
+                << ". Numeric expression expected afer 'AxisAmp', switching to default value" << std::endl;
+            if (iToken == tokens.size())
+              continue;
+          }
+          iToken++;
+        }
+
+        // no more arguments expected except for the actual command
+        if (iToken == tokens.size())
+          continue;
+
+        std::string commandStr;
+        while (iToken != tokens.size())
+          commandStr += tokens[iToken++] + " ";
+
+        // evaluate the command
+        CommandEvaluation eval = CommandExecutor::evaluate(commandStr);
+        if (!eval.isValid())
+          continue;
+
+        // check for param command
+        int paramIndex = eval.getConsoleCommand()->getAxisParamIndex();
+        if (paramIndex >= 0)
+        {
+          // parameter supported command
+          ParamCommand* cmd = new ParamCommand();
+          cmd->paramModifier_ = paramModifier;
+          cmd->bRelative_ = eval.getConsoleCommand()->getIsAxisRelative();
+
+          // add command to the buffer if not yet existing
+          for (unsigned int iParamCmd = 0; iParamCmd < paramCommandBuffer.size(); iParamCmd++)
+          {
+            if (getLowercase(paramCommandBuffer[iParamCmd]->evaluation_.getOriginalCommand())
+                == getLowercase(commandStr))
+            {
+              // already in list
+              cmd->paramCommand_ = paramCommandBuffer[iParamCmd];
+              break;
+            }
+          }
+          if (cmd->paramCommand_ == 0)
+          {
+            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)
+          {
+            if (!addParamCommand(cmd))
+            {
+              mode = eval.getConsoleCommand()->getKeybindMode();
+              commands[mode].push_back(cmd);
+            }
+          }
+        }
+        else
+        {
+          SimpleCommand* cmd = new SimpleCommand();
+          cmd->evaluation_ = eval;
+
+          if (mode == KeybindMode::None)
+            mode = eval.getConsoleCommand()->getKeybindMode();
+
+          commands[mode].push_back(cmd);
+        }
+      }
+    }
+
+    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] = 0;
+    }
+  }
+
+  bool Button::execute(KeybindMode::Enum 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;
+  }
+
+  // ###############################
+  // #####      HalfAxis       #####
+  // ###############################
+
+  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;
+    }
+    else
+    {
+      nParamCommands_ = 0; 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;
+  }
+
+  bool HalfAxis::execute()
+  {
+    bool success = true;
+    for (unsigned int i = 0; i < nParamCommands_; i++)
+      success = success && paramCommands_[i]->execute(absVal_, relVal_);
+    return success;
+  }
+
+
+  // ###############################
+  // ######     KeyBinder     ######
+  // ###############################
+
+  /**
+    @brief Constructor that does as little as necessary.
+  */
+  KeyBinder::KeyBinder() : deriveTime_(0.0f)
+  {
+    mouseRelative_[0] = 0;
+    mouseRelative_[1] = 0;
+    mousePosition_[0] = 0;
+    mousePosition_[1] = 0;
+
+    RegisterObject(KeyBinder);
+
+    // keys
+    std::string keyNames[] = {
+      "UNASSIGNED",
+      "ESCAPE",
+      "1", "2", "3", "4", "5", "6", "7", "8", "9", "0",
+      "MINUS", "EQUALS", "BACK", "TAB",
+      "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P",
+      "LBRACKET", "RBRACKET",
+      "RETURN", "LCONTROL",
+      "A", "S", "D", "F", "G", "H", "J", "K", "L",
+      "SEMICOLON", "APOSTROPHE", "GRAVE",
+      "LSHIFT", "BACKSLASH",
+      "Z", "X", "C", "V", "B", "N", "M",
+      "COMMA", "PERIOD", "SLASH",
+      "RSHIFT",
+      "MULTIPLY",
+      "LMENU",
+      "SPACE",
+      "CAPITAL",
+      "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10",
+      "NUMLOCK", "SCROLL",
+      "NUMPAD7", "NUMPAD8", "NUMPAD9",
+      "SUBTRACT",
+      "NUMPAD4", "NUMPAD5", "NUMPAD6",
+      "ADD",
+      "NUMPAD1", "NUMPAD2", "NUMPAD3", "NUMPAD0",
+      "DECIMAL",
+      "","",
+      "OEM_102",
+      "F11", "F12",
+      "","","","","","","","","","","",
+      "F13", "F14", "F15",
+      "","","","","","","","","","",
+      "KANA",
+      "","",
+      "ABNT_C1",
+      "","","","","",
+      "CONVERT",
+      "",
+      "NOCONVERT",
+      "",
+      "YEN",
+      "ABNT_C2",
+      "","","","","","","","","","","","","","",
+      "NUMPADEQUALS",
+      "","",
+      "PREVTRACK",
+      "AT",
+      "COLON", "UNDERLINE",
+      "KANJI",
+      "STOP",
+      "AX",
+      "UNLABELED",
+      "NEXTTRACK",
+      "","",
+      "NUMPADENTER",
+      "RCONTROL",
+      "","",
+      "MUTE",
+      "CALCULATOR",
+      "PLAYPAUSE",
+      "",
+      "MEDIASTOP",
+      "","","","","","","","","",
+      "VOLUMEDOWN",
+      "",
+      "VOLUMEUP",
+      "",
+      "WEBHOME",
+      "NUMPADCOMMA",
+      "",
+      "DIVIDE",
+      "",
+      "SYSRQ",
+      "RMENU",
+      "","","","","","","","","","","","",
+      "PAUSE",
+      "",
+      "HOME",
+      "UP",
+      "PGUP",
+      "",
+      "LEFT",
+      "",
+      "RIGHT",
+      "",
+      "END", "DOWN", "PGDOWN", "INSERT", "DELETE",
+      "","","","","","","",
+      "LWIN", "RWIN", "APPS",
+      "POWER", "SLEEP",
+      "","","",
+      "WAKE",
+      "",
+      "WEBSEARCH", "WEBFAVORITES", "WEBREFRESH", "WEBSTOP", "WEBFORWARD", "WEBBACK",
+      "MYCOMPUTER", "MAIL", "MEDIASELECT"
+    };
+    for (unsigned int i = 0; i < nKeys_s; i++)
+      keys_[i].name_ = "Key" + keyNames[i];
+
+    // mouse buttons
+    std::string mouseButtonNames[] = {
+      "MouseLeft", "MouseRight", "MouseMiddle",
+      "MouseButton3", "MouseButton4", "MouseButton5",
+      "MouseButton6", "MouseButton7",
+      "MouseWheel1Up", "MouseWheel1Down",
+      "MouseWheel2Up", "MouseWheel2Down" };
+    for (unsigned int i = 0; i < nMouseButtons_s; i++)
+      mouseButtons_[i].name_ = mouseButtonNames[i];
+
+    // joy stick buttons
+    for (unsigned int i = 0; i < 32; i++)
+      joyStickButtons_[i].name_ = "JoyButton" + getConvertedValue<int, std::string>(i);
+    for (unsigned int i = 32; i < nJoyStickButtons_s; i += 4)
+    {
+		  joyStickButtons_[i + 0].name_ = "JoyPOV" + getConvertedValue<int, std::string>((i - 32)/4 + 1) + "North";
+		  joyStickButtons_[i + 1].name_ = "JoyPOV" + getConvertedValue<int, std::string>((i - 32)/4 + 1) + "South";
+		  joyStickButtons_[i + 2].name_ = "JoyPOV" + getConvertedValue<int, std::string>((i - 32)/4 + 1) + "East";
+		  joyStickButtons_[i + 3].name_ = "JoyPOV" + getConvertedValue<int, std::string>((i - 32)/4 + 1) + "West";
+    }
+
+    // half axes
+    std::string rawNames[nHalfAxes_s/2];
+    rawNames[0] = "MouseX";
+    rawNames[1] = "MouseY";
+    rawNames[2] = "Empty1";
+    rawNames[3] = "Empty2";
+    for (unsigned int i = 4; i < nHalfAxes_s/2; i++)
+      rawNames[i] = "JoyAxis" + getConvertedValue<int, std::string>(i - 3);
+    for (unsigned int i = 0; i < nHalfAxes_s/2; i++)
+    {
+      halfAxes_[i * 2 + 0].name_ = rawNames[i] + "Pos";
+      halfAxes_[i * 2 + 1].name_ = rawNames[i] + "Neg";
+    }
+
+    for (unsigned int i = 0; i < this->nHalfAxes_s; i++)
+      halfAxes_[i].buttonThreshold_ = buttonThreshold_;
+  }
+
+  /**
+    @brief Destructor
+  */
+  KeyBinder::~KeyBinder()
+  {
+    // almost no destructors required because most of the arrays are static.
+    clearBindings(); // does some destruction work
+  }
+
+  /**
+    @brief Loads the key and button bindings.
+    @return True if loading succeeded.
+  */
+  void KeyBinder::loadBindings()
+  {
+    COUT(3) << "KeyBinder: Loading key bindings..." << std::endl;
+
+    clearBindings();
+
+    std::ifstream infile;
+    infile.open("keybindings.ini");
+    if (!infile.is_open())
+    {
+      ConfigFileManager::getSingleton()->setFile(CFT_Keybindings, "def_keybindings.ini");
+      ConfigFileManager::getSingleton()->save(CFT_Keybindings, "keybindings.ini");
+    }
+    infile.close();
+    ConfigFileManager::getSingleton()->setFile(CFT_Keybindings, "keybindings.ini");
+
+    // parse key bindings
+    setConfigValues();
+
+    COUT(3) << "KeyBinder: Loading key bindings done." << std::endl;
+  }
+
+  /**
+    @brief Loader for the key bindings, managed by config values.
+  */
+  void KeyBinder::setConfigValues()
+  {
+    SetConfigValueGeneric(KeyBinder, analogThreshold_, 0.01f)  .description("Threshold for analog axes until which the state is 0.");
+    SetConfigValueGeneric(KeyBinder, mouseSensitivity_, 1.0f)  .description("Mouse sensitivity.");
+    SetConfigValueGeneric(KeyBinder, bDeriveMouseInput_, false).description("Whether or not to derive moues movement for the absolute value.");
+    SetConfigValueGeneric(KeyBinder, derivePeriod_, 0.5f).description("Accuracy of the mouse input deriver. The higher the more precise, but laggier.");
+    SetConfigValueGeneric(KeyBinder, mouseSensitivityDerived_, 1.0f).description("Mouse sensitivity if mouse input is derived.");
+    SetConfigValueGeneric(KeyBinder, bClipMouse_, true).description("Whether or not to clip absolute value of mouse in non derive mode.");
+
+    float oldThresh = buttonThreshold_;
+    SetConfigValueGeneric(KeyBinder, buttonThreshold_, 0.80f).description("Threshold for analog axes until which the button is not pressed.");
+    if (oldThresh != buttonThreshold_)
+      for (unsigned int i = 0; i < nHalfAxes_s; i++)
+        if (halfAxes_[i].buttonThreshold_ == oldThresh)
+          halfAxes_[i].buttonThreshold_ = buttonThreshold_;
+
+    // keys
+    for (unsigned int i = 0; i < nKeys_s; i++)
+      readTrigger(keys_[i]);
+    // mouse buttons
+    for (unsigned int i = 0; i < nMouseButtons_s; i++)
+      readTrigger(mouseButtons_[i]);
+    // joy stick buttons
+    for (unsigned int i = 0; i < nJoyStickButtons_s; i++)
+      readTrigger(joyStickButtons_[i]);
+    // half axes
+    for (unsigned int i = 0; i < nHalfAxes_s; i++)
+      readTrigger(halfAxes_[i]);
+  }
+
+  void KeyBinder::readTrigger(Button& button)
+  {
+    // config value stuff
+    ConfigValueContainer* cont = ClassManager<KeyBinder>::getIdentifier()->getConfigValueContainer(button.name_);
+    if (!cont)
+    {
+      cont = new ConfigValueContainer(CFT_Keybindings, ClassManager<KeyBinder>::getIdentifier(), button.name_, "");
+      ClassManager<KeyBinder>::getIdentifier()->addConfigValueContainer(button.name_, cont);
+    }
+    std::string old = button.bindingString_;
+    cont->getValue(&button.bindingString_);
+
+    // keybinder stuff
+    if (old != button.bindingString_)
+    {
+      // clear everything so we don't get old axis ParamCommands mixed up
+      button.clear();
+
+      // binding has changed
+      button.parse(paramCommandBuffer_);
+    }
+  }
+
+  /**
+    @brief Overwrites all bindings with ""
+  */
+  void KeyBinder::clearBindings()
+  {
+    for (unsigned int i = 0; i < nKeys_s; i++)
+      keys_[i].clear();
+
+    for (unsigned int i = 0; i < nMouseButtons_s; i++)
+      mouseButtons_[i].clear();
+
+    for (unsigned int i = 0; i < nJoyStickButtons_s; i++)
+      joyStickButtons_[i].clear();
+
+    for (unsigned int i = 0; i < nHalfAxes_s; i++)
+      halfAxes_[i].clear();
+
+    for (unsigned int i = 0; i < paramCommandBuffer_.size(); i++)
+      delete paramCommandBuffer_[i];
+    paramCommandBuffer_.clear();
+  }
+
+  void KeyBinder::resetJoyStickAxes()
+  {
+    for (unsigned int i = 8; i < nHalfAxes_s; i++)
+    {
+      halfAxes_[i].absVal_ = 0.0f;
+      halfAxes_[i].relVal_ = 0.0f;
+    }
+  }
+
+  void KeyBinder::tickInput(float dt, const HandlerState& state)
+  {
+    // we have to process all the analog input since there is e.g. no 'mouseDoesntMove' event.
+    unsigned int iBegin = 8;
+    unsigned int iEnd   = 8;
+    if (state.joyStick)
+      iEnd = nHalfAxes_s;
+    if (state.mouse)
+      iBegin = 0;
+    for (unsigned int i = iBegin; i < iEnd; i++)
+    {
+      if (halfAxes_[i].hasChanged_)
+      {
+        if (!halfAxes_[i].wasDown_ && halfAxes_[i].absVal_ > halfAxes_[i].buttonThreshold_)
+        {
+          halfAxes_[i].wasDown_ = true;
+          if (halfAxes_[i].nCommands_[KeybindMode::OnPress])
+            halfAxes_[i].execute(KeybindMode::OnPress);
+        }
+        else if (halfAxes_[i].wasDown_ && halfAxes_[i].absVal_ < halfAxes_[i].buttonThreshold_)
+        {
+          halfAxes_[i].wasDown_ = false;
+          if (halfAxes_[i].nCommands_[KeybindMode::OnRelease])
+            halfAxes_[i].execute(KeybindMode::OnRelease);
+        }
+        halfAxes_[i].hasChanged_ = false;
+      }
+
+      if (halfAxes_[i].wasDown_)
+      {
+        if (halfAxes_[i].nCommands_[KeybindMode::OnHold])
+          halfAxes_[i].execute(KeybindMode::OnHold);
+      }
+
+      // these are the actually useful axis bindings for analog input AND output
+      if (halfAxes_[i].relVal_ > analogThreshold_ || halfAxes_[i].absVal_ > analogThreshold_)
+      {
+        //COUT(3) << halfAxes_[i].name_ << "\t" << halfAxes_[i].absVal_ << std::endl;
+        halfAxes_[i].execute();
+      }
+    }
+
+    if (bDeriveMouseInput_ && state.mouse)
+    {
+      if (deriveTime_ > derivePeriod_)
+      {
+        //CCOUT(3) << "mouse abs: ";
+        for (int i = 0; i < 2; i++)
+        {
+          if (mouseRelative_[i] > 0)
+          {
+            halfAxes_[2*i + 0].absVal_ =  mouseRelative_[i] / deriveTime_ * 0.0005 * mouseSensitivityDerived_;
+            halfAxes_[2*i + 1].absVal_ = 0.0f;
+          }
+          else if (mouseRelative_[i] < 0)
+          {
+            halfAxes_[2*i + 0].absVal_ = 0.0f;
+            halfAxes_[2*i + 1].absVal_ = -mouseRelative_[i] / deriveTime_ * 0.0005 * mouseSensitivityDerived_;
+          }
+          else
+          {
+            halfAxes_[2*i + 0].absVal_ = 0.0f;
+            halfAxes_[2*i + 1].absVal_ = 0.0f;
+          }
+          //COUT(3) << mouseRelative_[i] << " | ";
+          mouseRelative_[i] = 0;
+          halfAxes_[2*i + 0].hasChanged_ = true;
+          halfAxes_[2*i + 1].hasChanged_ = true;
+        }
+        deriveTime_ = 0.0f;
+        //COUT(3) << std::endl;
+      }
+      else
+        deriveTime_ += dt;
+    }
+
+    // execute all buffered bindings (addional parameter)
+    for (unsigned int i = 0; i < paramCommandBuffer_.size(); i++)
+      paramCommandBuffer_[i]->execute();
+
+    // always reset the relative movement of the mouse
+    if (state.mouse)
+      for (unsigned int i = 0; i < 8; i++)
+        halfAxes_[i].relVal_ = 0.0f;
+  }
+
+  void KeyBinder::keyPressed (const KeyEvent& evt)
+  { keys_[evt.key].execute(KeybindMode::OnPress); }
+
+  void KeyBinder::keyReleased(const KeyEvent& evt)
+  { keys_[evt.key].execute(KeybindMode::OnRelease); }
+
+  void KeyBinder::keyHeld    (const KeyEvent& evt)
+  { keys_[evt.key].execute(KeybindMode::OnHold); }
+
+
+  void KeyBinder::mouseButtonPressed (MouseButton::Enum id)
+  { mouseButtons_[id].execute(KeybindMode::OnPress); }
+
+  void KeyBinder::mouseButtonReleased(MouseButton::Enum id)
+  { mouseButtons_[id].execute(KeybindMode::OnRelease); }
+
+  void KeyBinder::mouseButtonHeld    (MouseButton::Enum id)
+  { mouseButtons_[id].execute(KeybindMode::OnHold); }
+
+
+  void KeyBinder::joyStickButtonPressed (int joyStickID, int button)
+  { joyStickButtons_[button].execute(KeybindMode::OnPress); }
+
+  void KeyBinder::joyStickButtonReleased(int joyStickID, int button)
+  { joyStickButtons_[button].execute(KeybindMode::OnRelease); }
+
+  void KeyBinder::joyStickButtonHeld    (int joyStickID, int button)
+  { joyStickButtons_[button].execute(KeybindMode::OnHold); }
+
+  /**
+    @brief Event handler for the mouseMoved Event.
+    @param e Mouse state information
+  */
+  void KeyBinder::mouseMoved(IntVector2 abs_, IntVector2 rel_, IntVector2 clippingSize)
+  {
+    // y axis of mouse input is inverted
+    int rel[] = { rel_.x, -rel_.y };
+
+    if (!bDeriveMouseInput_)
+    {
+      for (int i = 0; i < 2; i++)
+      {
+        if (rel[i])
+        {
+          // absolute
+          halfAxes_[2*i + 0].hasChanged_ = true;
+          halfAxes_[2*i + 1].hasChanged_ = true;
+          mousePosition_[i] += rel[i];
+
+          if (bClipMouse_)
+          {
+            if (mousePosition_[i] > 1024)
+              mousePosition_[i] =  1024;
+            if (mousePosition_[i] < -1024)
+              mousePosition_[i] = -1024;
+          }
+
+          if (mousePosition_[i] >= 0)
+          {
+            halfAxes_[2*i + 0].absVal_ =   mousePosition_[i]/1024.0f * mouseSensitivity_;
+            halfAxes_[2*i + 1].absVal_ =  0.0f;
+          }
+          else
+          {
+            halfAxes_[2*i + 0].absVal_ =  0.0f;
+            halfAxes_[2*i + 1].absVal_ =  -mousePosition_[i]/1024.0f * mouseSensitivity_;
+          }
+        }
+      }
+    }
+    else
+    {
+      mouseRelative_[0] += rel[0];
+      mouseRelative_[1] += rel[1];
+    }
+
+    // relative
+    for (int i = 0; i < 2; i++)
+    {
+      if (rel[i] > 0)
+        halfAxes_[0 + 2*i].relVal_ =  ((float)rel[i])/1024 * mouseSensitivity_;
+      else
+        halfAxes_[1 + 2*i].relVal_ = -((float)rel[i])/1024 * mouseSensitivity_;
+    }
+  }
+
+  /**
+    @brief Event handler for the mouseScrolled Event.
+    @param e Mouse state information
+  */
+  void KeyBinder::mouseScrolled(int abs, int rel)
+  {
+    //COUT(3) << mouseButtons_[8].name_ << "   " << abs << " | " << rel << std::endl;
+
+    if (rel > 0)
+      for (int i = 0; i < rel/120; i++)
+        mouseButtons_[8].execute(KeybindMode::OnPress, ((float)abs)/120.0f);
+    else
+      for (int i = 0; i < -rel/120; i++)
+        mouseButtons_[9].execute(KeybindMode::OnPress, ((float)abs)/120.0f);
+  }
+
+  void KeyBinder::joyStickAxisMoved(int joyStickID, int axis, float value)
+  {
+    // TODO: Use proper calibration values instead of generally 16-bit integer
+    int i = 8 + axis * 2;
+    if (value >= 0)
+    {
+      //if (value > 10000)
+      //{ CCOUT(3) << halfAxes_[i].name_ << std::endl; }
+
+      halfAxes_[i].absVal_ = value;
+      halfAxes_[i].relVal_ = value;
+      halfAxes_[i].hasChanged_ = true;
+      if (halfAxes_[i + 1].absVal_ > 0.0f)
+      {
+        halfAxes_[i + 1].absVal_ = -0.0f;
+        halfAxes_[i + 1].relVal_ = -0.0f;
+        halfAxes_[i + 1].hasChanged_ = true;
+      }
+    }
+    else
+    {
+      //if (value < -10000)
+      //{ CCOUT(3) << halfAxes_[i + 1].name_ << std::endl; }
+
+      halfAxes_[i + 1].absVal_ = -value;
+      halfAxes_[i + 1].relVal_ = -value;
+      halfAxes_[i + 1].hasChanged_ = true;
+      if (halfAxes_[i].absVal_ > 0.0f)
+      {
+        halfAxes_[i].absVal_ = -0.0f;
+        halfAxes_[i].relVal_ = -0.0f;
+        halfAxes_[i].hasChanged_ = true;
+      }
+    }
+  }
+
+
+  // ###############################
+  // #####     KeyDetector     #####
+  // ###############################
+
+  /**
+    @brief Constructor
+  */
+  KeyDetector::KeyDetector()
+  {
+    RegisterObject(KeyDetector);
+  }
+
+  /**
+    @brief Destructor
+  */
+  KeyDetector::~KeyDetector()
+  {
+  }
+
+  /**
+    @brief Loads the key and button bindings.
+    @return True if loading succeeded.
+  */
+  void KeyDetector::loadBindings()
+  {
+    clearBindings();
+    setConfigValues();
+  }
+
+  void KeyDetector::readTrigger(Button& button)
+  {
+    SimpleCommand* cmd = new SimpleCommand();
+    cmd->evaluation_ = CommandExecutor::evaluate("storeKeyStroke " + button.name_);
+    button.commands_[KeybindMode::OnPress] = new BaseCommand*[1];
+    button.commands_[KeybindMode::OnPress][0] = cmd;
+    button.nCommands_[KeybindMode::OnPress] = 1;
+  }
+
+
+  // ###############################
+  // ##### CalibratorCallback  #####
+  // ###############################
+
+  void CalibratorCallback::keyPressed(const orxonox::KeyEvent &evt)
+  {
+    if (evt.key == KeyCode::Return)
+    {
+      InputManager::setInputState(InputManager::IS_NOCALIBRATE);
+    }
+  }
+}
Index: code/trunk/src/core/KeyBinder.h
===================================================================
--- code/trunk/src/core/KeyBinder.h	(revision 1502)
+++ code/trunk/src/core/KeyBinder.h	(revision 1502)
@@ -0,0 +1,259 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   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 _KeyBinder_H__
+#define _KeyBinder_H__
+
+#include "CorePrereqs.h"
+
+#include <string>
+#include <vector>
+
+#include "ois/OIS.h"
+#include "util/Math.h"
+#include "OrxonoxClass.h"
+#include "CommandEvaluation.h"
+#include "InputInterfaces.h"
+
+namespace orxonox
+{
+  class _CoreExport BufferedParamCommand
+  {
+  public:
+    BufferedParamCommand() : value_(0.0f), nValuesAdded_(0), paramIndex_(-1) { }
+    bool execute();
+
+    float value_;
+    unsigned int nValuesAdded_;
+    int paramIndex_;
+    CommandEvaluation evaluation_;
+  };
+
+  class _CoreExport BaseCommand
+  {
+  public:
+    virtual ~BaseCommand() { }
+    virtual bool execute(float abs = 1.0f, float rel = 1.0f) = 0;
+  };
+
+  class _CoreExport SimpleCommand : public BaseCommand
+  {
+  public:
+    bool execute(float abs = 1.0f, float rel = 1.0f);
+
+    CommandEvaluation evaluation_;
+  };
+
+  class _CoreExport ParamCommand : public BaseCommand
+  {
+  public:
+    ParamCommand() : bRelative_(false), paramModifier_(1.0f), paramCommand_(0) { }
+    bool execute(float abs = 1.0f, float rel = 1.0f);
+
+    bool bRelative_;
+    float paramModifier_;
+    BufferedParamCommand* paramCommand_;
+  };
+
+  class _CoreExport Button
+  {
+  public:
+    Button() { nCommands_[0]=0; nCommands_[1]=0; nCommands_[2]=0; clear(); }
+    virtual ~Button() { clear(); }
+    virtual void clear();
+    virtual bool addParamCommand(ParamCommand* command) { return false; }
+    void parse(std::vector<BufferedParamCommand*>& paramCommandBuffer);
+    bool execute(KeybindMode::Enum 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_;
+    //! 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_;
+  };
+
+
+  class _CoreExport HalfAxis : public Button
+  {
+  public:
+    HalfAxis() : relVal_(0.0f), absVal_(0.0f), paramCommands_(0), nParamCommands_(0),
+                 wasDown_(false), hasChanged_(false) { }
+    using Button::execute;
+    bool execute();
+    //bool execute(KeybindMode::Enum mode) { return Button::execute(mode); }
+    bool addParamCommand(ParamCommand* command);
+    void clear();
+
+    // axis related
+    float relVal_;
+    float absVal_;
+    ParamCommand** paramCommands_;
+    unsigned int nParamCommands_;
+
+    // button related
+    bool wasDown_;
+    bool hasChanged_;
+  };
+
+
+  /**
+    @brief Handles mouse, keyboard and joy stick input while in the actual game mode.
+           Manages the key bindings.
+  */
+  class _CoreExport KeyBinder : public KeyHandler, public MouseHandler, public JoyStickHandler, public OrxonoxClass
+  {
+  public:
+    KeyBinder ();
+    virtual ~KeyBinder();
+
+    void loadBindings();
+    void clearBindings();
+    void setConfigValues();
+    void resetJoyStickAxes();
+
+  protected: // functions
+    void tickInput(float dt, const HandlerState& state);
+
+    virtual void readTrigger(Button& button);
+
+    void keyPressed (const KeyEvent& evt);
+    void keyReleased(const KeyEvent& evt);
+    void keyHeld    (const KeyEvent& evt);
+
+    void mouseButtonPressed (MouseButton::Enum id);
+    void mouseButtonReleased(MouseButton::Enum id);
+    void mouseButtonHeld    (MouseButton::Enum id);
+    void mouseMoved         (IntVector2 abs, IntVector2 rel, IntVector2 clippingSize);
+    void mouseScrolled      (int abs, int rel);
+
+    void joyStickButtonPressed (int joyStickID, int button);
+    void joyStickButtonReleased(int joyStickID, int button);
+    void joyStickButtonHeld    (int joyStickID, int button);
+    void joyStickAxisMoved     (int joyStickID, int axis, float value);
+
+  protected: // variables
+    //! denotes the number of different keys there are in OIS.
+    static const unsigned int nKeys_s = 0xEE;
+    //! Actual key bindings as bundle for Press, Hold and Release
+    Button keys_ [nKeys_s];
+
+    //! denotes the number of different mouse buttons there are in OIS.
+    static const unsigned int nMouseButtons_s = 8 + 2*2; // 8 buttons and 2 scroll wheels
+    //! Actual key bindings as bundle for Press, Hold and Release
+    Button mouseButtons_ [nMouseButtons_s];
+
+    //! denotes the number of different joy stick buttons there are in OIS.
+    static const unsigned int nJoyStickButtons_s = 32 + 4 * 4; // 32 buttons and 4 POVs with 4 buttons
+    //! Actual key bindings as bundle for Press, Hold and Release
+    Button joyStickButtons_ [nJoyStickButtons_s];
+
+    //! denotes the number of half axes (every axis twice) there can be.
+    static const unsigned int nHalfAxes_s = 56;
+    /**
+    * Array with all the half axes for mouse and joy sticks.
+    * Keep in mind that the positions are fixed and that the first entry is the
+    * positive one and the second is negative.
+    * Sequence is as follows:
+    *  0 -  3: Mouse x and y
+    *  4 -  7: empty
+    *  8 - 23: joy stick slider axes 1 to 8
+    * 24 - 55: joy stick axes 1 - 16
+    */
+    HalfAxis halfAxes_[nHalfAxes_s];
+
+    /**
+    * Commands that have additional parameters (axes) are executed at the end of
+    * the tick() so that all values can be buffered for single execution.
+    */
+    std::vector<BufferedParamCommand*> paramCommandBuffer_;
+
+    //! Keeps track of the absolute mouse value (incl. scroll wheel)
+    int mousePosition_[2];
+    //! Used to derive mouse input if requested
+    int mouseRelative_[2];
+    float deriveTime_;
+
+    //##### ConfigValues #####
+    //! 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_;
+    //! Whether or not to clip abslute mouse values to 1024
+    bool bClipMouse_;
+  };
+
+
+  class _CoreExport KeyDetector : public KeyBinder
+  {
+  public:
+    KeyDetector();
+    ~KeyDetector();
+    void loadBindings();
+
+  protected:
+    void readTrigger(Button& button);
+  };
+
+  class _CoreExport CalibratorCallback : public KeyHandler
+  {
+  public:
+    CalibratorCallback() {}
+    ~CalibratorCallback() {}
+
+  private:
+    void keyPressed (const KeyEvent& evt);
+    void keyReleased(const KeyEvent& evt) {}
+    void keyHeld    (const KeyEvent& evt) {}
+
+    void tickInput(float dt, const HandlerState &state) { }
+  };
+}
+
+
+
+
+#endif /* _KeyBinder_H__ */
Index: code/trunk/src/core/Language.cc
===================================================================
--- code/trunk/src/core/Language.cc	(revision 1407)
+++ code/trunk/src/core/Language.cc	(revision 1502)
@@ -37,4 +37,6 @@
 
 #include "CoreSettings.h"
+
+#include "Debug.h"
 
 namespace orxonox
Index: code/trunk/src/core/Language.h
===================================================================
--- code/trunk/src/core/Language.h	(revision 1407)
+++ code/trunk/src/core/Language.h	(revision 1502)
@@ -50,5 +50,4 @@
 #include <map>
 #include <string>
-
 
 #define AddLanguageEntry(label, fallbackstring) \
Index: code/trunk/src/core/OrxonoxClass.cc
===================================================================
--- code/trunk/src/core/OrxonoxClass.cc	(revision 1407)
+++ code/trunk/src/core/OrxonoxClass.cc	(revision 1502)
@@ -33,4 +33,6 @@
 
 #include "OrxonoxClass.h"
+#include "MetaObjectList.h"
+#include "Identifier.h"
 
 namespace orxonox
@@ -41,4 +43,6 @@
       parents_(0)
     {
+        this->metaList_ = new MetaObjectList();
+
         this->setConfigValues();
     }
@@ -47,7 +51,88 @@
     OrxonoxClass::~OrxonoxClass()
     {
+        delete this->metaList_;
+
         // parents_ exists only if isCreatingHierarchy() of the associated Identifier returned true while creating the class
         if (this->parents_)
             delete this->parents_;
     }
+
+    /** @brief Returns true if the objects class is of the given type or a derivative. */
+    bool OrxonoxClass::isA(const Identifier* identifier)
+        { return this->getIdentifier()->isA(identifier); }
+    /** @brief Returns true if the objects class is exactly of the given type. */
+    bool OrxonoxClass::isExactlyA(const Identifier* identifier)
+        { return this->getIdentifier()->isExactlyA(identifier); }
+    /** @brief Returns true if the objects class is a child of the given type. */
+    bool OrxonoxClass::isChildOf(const Identifier* identifier)
+        { return this->getIdentifier()->isChildOf(identifier); }
+    /** @brief Returns true if the objects class is a direct child of the given type. */
+    bool OrxonoxClass::isDirectChildOf(const Identifier* identifier)
+        { return this->getIdentifier()->isDirectChildOf(identifier); }
+    /** @brief Returns true if the objects class is a parent of the given type. */
+    bool OrxonoxClass::isParentOf(const Identifier* identifier)
+        { return this->getIdentifier()->isParentOf(identifier); }
+    /** @brief Returns true if the objects class is a direct parent of the given type. */
+    bool OrxonoxClass::isDirectParentOf(const Identifier* identifier)
+        { return this->getIdentifier()->isDirectParentOf(identifier); }
+
+
+    /** @brief Returns true if the objects class is of the given type or a derivative. */
+    bool OrxonoxClass::isA(const SubclassIdentifier<class B>* identifier)
+        { return this->getIdentifier()->isA(identifier->getIdentifier()); }
+    /** @brief Returns true if the objects class is exactly of the given type. */
+    bool OrxonoxClass::isExactlyA(const SubclassIdentifier<class B>* identifier)
+        { return this->getIdentifier()->isExactlyA(identifier->getIdentifier()); }
+    /** @brief Returns true if the objects class is a child of the given type. */
+    bool OrxonoxClass::isChildOf(const SubclassIdentifier<class B>* identifier)
+        { return this->getIdentifier()->isChildOf(identifier->getIdentifier()); }
+    /** @brief Returns true if the objects class is a direct child of the given type. */
+    bool OrxonoxClass::isDirectChildOf(const SubclassIdentifier<class B>* identifier)
+        { return this->getIdentifier()->isDirectChildOf(identifier->getIdentifier()); }
+    /** @brief Returns true if the objects class is a parent of the given type. */
+    bool OrxonoxClass::isParentOf(const SubclassIdentifier<class B>* identifier)
+        { return this->getIdentifier()->isParentOf(identifier->getIdentifier()); }
+    /** @brief Returns true if the objects class is a direct parent of the given type. */
+    bool OrxonoxClass::isDirectParentOf(const SubclassIdentifier<class B>* identifier)
+        { return this->getIdentifier()->isDirectParentOf(identifier->getIdentifier()); }
+
+
+    /** @brief Returns true if the objects class is of the given type or a derivative. */
+    bool OrxonoxClass::isA(const SubclassIdentifier<class B> identifier)
+        { return this->getIdentifier()->isA(identifier.getIdentifier()); }
+    /** @brief Returns true if the objects class is exactly of the given type. */
+    bool OrxonoxClass::isExactlyA(const SubclassIdentifier<class B> identifier)
+        { return this->getIdentifier()->isExactlyA(identifier.getIdentifier()); }
+    /** @brief Returns true if the objects class is a child of the given type. */
+    bool OrxonoxClass::isChildOf(const SubclassIdentifier<class B> identifier)
+        { return this->getIdentifier()->isChildOf(identifier.getIdentifier()); }
+    /** @brief Returns true if the objects class is a direct child of the given type. */
+    bool OrxonoxClass::isDirectChildOf(const SubclassIdentifier<class B> identifier)
+        { return this->getIdentifier()->isDirectChildOf(identifier.getIdentifier()); }
+    /** @brief Returns true if the objects class is a parent of the given type. */
+    bool OrxonoxClass::isParentOf(const SubclassIdentifier<class B> identifier)
+        { return this->getIdentifier()->isParentOf(identifier.getIdentifier()); }
+    /** @brief Returns true if the objects class is a direct parent of the given type. */
+    bool OrxonoxClass::isDirectParentOf(const SubclassIdentifier<class B> identifier)
+        { return this->getIdentifier()->isDirectParentOf(identifier.getIdentifier()); }
+
+
+    /** @brief Returns true if the objects class is of the given type or a derivative. */
+    bool OrxonoxClass::isA(const OrxonoxClass* object)
+        { return this->getIdentifier()->isA(object->getIdentifier()); }
+    /** @brief Returns true if the objects class is exactly of the given type. */
+    bool OrxonoxClass::isExactlyA(const OrxonoxClass* object)
+        { return this->getIdentifier()->isExactlyA(object->getIdentifier()); }
+    /** @brief Returns true if the objects class is a child of the given type. */
+    bool OrxonoxClass::isChildOf(const OrxonoxClass* object)
+        { return this->getIdentifier()->isChildOf(object->getIdentifier()); }
+    /** @brief Returns true if the objects class is a direct child of the given type. */
+    bool OrxonoxClass::isDirectChildOf(const OrxonoxClass* object)
+        { return this->getIdentifier()->isDirectChildOf(object->getIdentifier()); }
+    /** @brief Returns true if the objects class is a parent of the given type. */
+    bool OrxonoxClass::isParentOf(const OrxonoxClass* object)
+        { return this->getIdentifier()->isParentOf(object->getIdentifier()); }
+    /** @brief Returns true if the objects class is a direct child of the given type. */
+    bool OrxonoxClass::isDirectParentOf(const OrxonoxClass* object)
+        { return this->getIdentifier()->isDirectParentOf(object->getIdentifier()); }
 }
Index: code/trunk/src/core/OrxonoxClass.h
===================================================================
--- code/trunk/src/core/OrxonoxClass.h	(revision 1407)
+++ code/trunk/src/core/OrxonoxClass.h	(revision 1502)
@@ -43,7 +43,4 @@
 #include <string>
 
-#include "MetaObjectList.h"
-#include "Iterator.h"
-
 namespace orxonox
 {
@@ -75,90 +72,39 @@
 
             /** @brief Returns the MetaObjectList of the object, containing a link to all ObjectLists and ObjectListElements the object is registered in. @return The list */
-            inline MetaObjectList& getMetaList() { return this->metaList_; }
+            inline MetaObjectList& getMetaList() { return (*this->metaList_); }
 
 
-            /** @brief Returns true if the objects class is of the given type or a derivative. */
-            inline bool isA(const Identifier* identifier)
-                { return this->getIdentifier()->isA(identifier); }
-            /** @brief Returns true if the objects class is exactly of the given type. */
-            inline bool isExactlyA(const Identifier* identifier)
-                { return this->getIdentifier()->isExactlyA(identifier); }
-            /** @brief Returns true if the objects class is a child of the given type. */
-            inline bool isChildOf(const Identifier* identifier)
-                { return this->getIdentifier()->isChildOf(identifier); }
-            /** @brief Returns true if the objects class is a direct child of the given type. */
-            inline bool isDirectChildOf(const Identifier* identifier)
-                { return this->getIdentifier()->isDirectChildOf(identifier); }
-            /** @brief Returns true if the objects class is a parent of the given type. */
-            inline bool isParentOf(const Identifier* identifier)
-                { return this->getIdentifier()->isParentOf(identifier); }
-            /** @brief Returns true if the objects class is a direct parent of the given type. */
-            inline bool isDirectParentOf(const Identifier* identifier)
-                { return this->getIdentifier()->isDirectParentOf(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);
 
+            bool isA(const SubclassIdentifier<class B>* identifier);
+            bool isExactlyA(const SubclassIdentifier<class B>* identifier);
+            bool isChildOf(const SubclassIdentifier<class B>* identifier);
+            bool isDirectChildOf(const SubclassIdentifier<class B>* identifier);
+            bool isParentOf(const SubclassIdentifier<class B>* identifier);
+            bool isDirectParentOf(const SubclassIdentifier<class B>* identifier);
 
-            /** @brief Returns true if the objects class is of the given type or a derivative. */
-            inline bool isA(const SubclassIdentifier<class B>* identifier)
-                { return this->getIdentifier()->isA(identifier->getIdentifier()); }
-            /** @brief Returns true if the objects class is exactly of the given type. */
-            inline bool isExactlyA(const SubclassIdentifier<class B>* identifier)
-                { return this->getIdentifier()->isExactlyA(identifier->getIdentifier()); }
-            /** @brief Returns true if the objects class is a child of the given type. */
-            inline bool isChildOf(const SubclassIdentifier<class B>* identifier)
-                { return this->getIdentifier()->isChildOf(identifier->getIdentifier()); }
-            /** @brief Returns true if the objects class is a direct child of the given type. */
-            inline bool isDirectChildOf(const SubclassIdentifier<class B>* identifier)
-                { return this->getIdentifier()->isDirectChildOf(identifier->getIdentifier()); }
-            /** @brief Returns true if the objects class is a parent of the given type. */
-            inline bool isParentOf(const SubclassIdentifier<class B>* identifier)
-                { return this->getIdentifier()->isParentOf(identifier->getIdentifier()); }
-            /** @brief Returns true if the objects class is a direct parent of the given type. */
-            inline bool isDirectParentOf(const SubclassIdentifier<class B>* identifier)
-                { return this->getIdentifier()->isDirectParentOf(identifier->getIdentifier()); }
+            bool isA(const SubclassIdentifier<class B> identifier);
+            bool isExactlyA(const SubclassIdentifier<class B> identifier);
+            bool isChildOf(const SubclassIdentifier<class B> identifier);
+            bool isDirectChildOf(const SubclassIdentifier<class B> identifier);
+            bool isParentOf(const SubclassIdentifier<class B> identifier);
+            bool isDirectParentOf(const SubclassIdentifier<class B> identifier);
 
-
-            /** @brief Returns true if the objects class is of the given type or a derivative. */
-            inline bool isA(const SubclassIdentifier<class B> identifier)
-                { return this->getIdentifier()->isA(identifier.getIdentifier()); }
-            /** @brief Returns true if the objects class is exactly of the given type. */
-            inline bool isExactlyA(const SubclassIdentifier<class B> identifier)
-                { return this->getIdentifier()->isExactlyA(identifier.getIdentifier()); }
-            /** @brief Returns true if the objects class is a child of the given type. */
-            inline bool isChildOf(const SubclassIdentifier<class B> identifier)
-                { return this->getIdentifier()->isChildOf(identifier.getIdentifier()); }
-            /** @brief Returns true if the objects class is a direct child of the given type. */
-            inline bool isDirectChildOf(const SubclassIdentifier<class B> identifier)
-                { return this->getIdentifier()->isDirectChildOf(identifier.getIdentifier()); }
-            /** @brief Returns true if the objects class is a parent of the given type. */
-            inline bool isParentOf(const SubclassIdentifier<class B> identifier)
-                { return this->getIdentifier()->isParentOf(identifier.getIdentifier()); }
-            /** @brief Returns true if the objects class is a direct parent of the given type. */
-            inline bool isDirectParentOf(const SubclassIdentifier<class B> identifier)
-                { return this->getIdentifier()->isDirectParentOf(identifier.getIdentifier()); }
-
-
-            /** @brief Returns true if the objects class is of the given type or a derivative. */
-            inline bool isA(const OrxonoxClass* object)
-                { return this->getIdentifier()->isA(object->getIdentifier()); }
-            /** @brief Returns true if the objects class is exactly of the given type. */
-            inline bool isExactlyA(const OrxonoxClass* object)
-                { return this->getIdentifier()->isExactlyA(object->getIdentifier()); }
-            /** @brief Returns true if the objects class is a child of the given type. */
-            inline bool isChildOf(const OrxonoxClass* object)
-                { return this->getIdentifier()->isChildOf(object->getIdentifier()); }
-            /** @brief Returns true if the objects class is a direct child of the given type. */
-            inline bool isDirectChildOf(const OrxonoxClass* object)
-                { return this->getIdentifier()->isDirectChildOf(object->getIdentifier()); }
-            /** @brief Returns true if the objects class is a parent of the given type. */
-            inline bool isParentOf(const OrxonoxClass* object)
-                { return this->getIdentifier()->isParentOf(object->getIdentifier()); }
-            /** @brief Returns true if the objects class is a direct child of the given type. */
-            inline bool isDirectParentOf(const OrxonoxClass* object)
-                { return this->getIdentifier()->isDirectParentOf(object->getIdentifier()); }
+            bool isA(const OrxonoxClass* object);
+            bool isExactlyA(const OrxonoxClass* object);
+            bool isChildOf(const OrxonoxClass* object);
+            bool isDirectChildOf(const OrxonoxClass* object);
+            bool isParentOf(const OrxonoxClass* object);
+            bool isDirectParentOf(const OrxonoxClass* object);
 
         private:
-            Identifier* identifier_;                    //!< The Identifier of the object
+            Identifier* identifier_;                   //!< The Identifier of the object
             std::set<const Identifier*>* parents_;     //!< List of all parents of the object
-            MetaObjectList metaList_;                   //!< MetaObjectList, containing all ObjectLists and ObjectListElements the object is registered in
+            MetaObjectList* metaList_;                 //!< MetaObjectList, containing all ObjectLists and ObjectListElements the object is registered in
     };
 }
Index: code/trunk/src/core/OutputBuffer.cc
===================================================================
--- code/trunk/src/core/OutputBuffer.cc	(revision 1502)
+++ code/trunk/src/core/OutputBuffer.cc	(revision 1502)
@@ -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:
+ *      ...
+ *
+ */
+
+#include "OutputBuffer.h"
+
+#define OUTPUTBUFFER_MAX_LINE_LENGTH 16384
+
+namespace orxonox
+{
+    void OutputBuffer::registerListener(OutputBufferListener* listener)
+    {
+        this->listeners_.insert(this->listeners_.end(), listener);
+    }
+
+    void OutputBuffer::unregisterListener(OutputBufferListener* listener)
+    {
+        for (std::list<OutputBufferListener*>::iterator it = this->listeners_.begin(); it != this->listeners_.end(); )
+        {
+            if ((*it) == listener)
+                this->listeners_.erase(it++);
+            else
+                ++it;
+        }
+    }
+
+    OutputBuffer& OutputBuffer::operator<<(std::ostream& (*manipulator)(std::ostream&))
+    {
+                this->stream_ << manipulator;
+                this->callListeners();
+                return *this;
+    }
+
+    OutputBuffer& OutputBuffer::operator<<(std::ios& (*manipulator)(std::ios&))
+    {
+                this->stream_ << manipulator;
+                this->callListeners();
+                return *this;
+    }
+
+    OutputBuffer& OutputBuffer::operator<<(std::ios_base& (*manipulator)(std::ios_base&))
+    {
+                this->stream_ << manipulator;
+                this->callListeners();
+                return *this;
+    }
+
+    bool OutputBuffer::getLine(std::string* output)
+    {
+        char line[OUTPUTBUFFER_MAX_LINE_LENGTH];
+
+        this->stream_.getline(line, OUTPUTBUFFER_MAX_LINE_LENGTH);
+        (*output) = std::string(line);
+
+        bool eof = this->stream_.eof();
+        bool fail = this->stream_.fail();
+
+        if (eof)
+            this->stream_.flush();
+
+        if (eof || fail)
+            this->stream_.clear();
+
+        return (!eof && !fail);
+    }
+
+    void OutputBuffer::callListeners()
+    {
+        for (std::list<OutputBufferListener*>::iterator it = this->listeners_.begin(); it != this->listeners_.end(); ++it)
+            (*it)->outputChanged();
+    }
+}
Index: code/trunk/src/core/OutputBuffer.h
===================================================================
--- code/trunk/src/core/OutputBuffer.h	(revision 1502)
+++ code/trunk/src/core/OutputBuffer.h	(revision 1502)
@@ -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 _OutputBuffer_H__
+#define _OutputBuffer_H__
+
+#include <list>
+#include <sstream>
+#include <iostream>
+
+#include "CorePrereqs.h"
+
+namespace orxonox
+{
+    class _CoreExport OutputBufferListener
+    {
+        friend class OutputBuffer;
+
+        public:
+            virtual ~OutputBufferListener() {}
+
+        private:
+            virtual void outputChanged() = 0;
+    };
+
+    class _CoreExport OutputBuffer
+    {
+        public:
+            OutputBuffer() {}
+            ~OutputBuffer() {}
+
+            template <class T>
+            inline OutputBuffer& operator<<(T object)
+            {
+                this->stream_ << object;
+                this->callListeners();
+                return *this;
+            }
+
+            OutputBuffer& operator<<(std::ostream& (*manipulator)(std::ostream&));
+            OutputBuffer& operator<<(std::ios& (*manipulator)(std::ios&));
+            OutputBuffer& operator<<(std::ios_base& (*manipulator)(std::ios_base&));
+
+            template <class T>
+            inline void add(T object)
+            {
+                this->stream_ << object;
+                this->callListeners();
+            }
+
+            template <class T>
+            inline void addLine(T object)
+            {
+                this->stream_ << object << std::endl;
+                this->callListeners();
+            }
+
+            inline void newline()
+            {
+                this->stream_ << std::endl;
+                this->callListeners();
+            }
+
+            inline void flush()
+            {
+                this->stream_.flush();
+            }
+
+            bool getLine(std::string* output);
+
+            void registerListener(OutputBufferListener* listener);
+            void unregisterListener(OutputBufferListener* listener);
+
+        private:
+            void callListeners();
+
+            std::stringstream stream_;
+            std::list<OutputBufferListener*> listeners_;
+    };
+}
+
+#endif /* _OutputBuffer_H__ */
Index: code/trunk/src/core/OutputHandler.cc
===================================================================
--- code/trunk/src/core/OutputHandler.cc	(revision 1407)
+++ code/trunk/src/core/OutputHandler.cc	(revision 1502)
@@ -35,8 +35,13 @@
 #include "CoreSettings.h"
 #include "ConsoleCommand.h"
+#include "Shell.h"
 
 namespace orxonox
 {
-    ConsoleCommandShortcutGeneric(log, createExecutor(createFunctor(&OutputHandler::log), "log", AccessLevel::None));
+    SetConsoleCommandShortcutGeneric(log,     createConsoleCommand(createFunctor(&OutputHandler::log),     "log"    ));
+    SetConsoleCommandShortcutGeneric(error,   createConsoleCommand(createFunctor(&OutputHandler::error),   "error"  ));
+    SetConsoleCommandShortcutGeneric(warning, createConsoleCommand(createFunctor(&OutputHandler::warning), "warning"));
+    SetConsoleCommandShortcutGeneric(info,    createConsoleCommand(createFunctor(&OutputHandler::info),    "info"   ));
+    SetConsoleCommandShortcutGeneric(debug,   createConsoleCommand(createFunctor(&OutputHandler::debug),   "debug"  ));
 
     /**
@@ -82,4 +87,14 @@
 
     /**
+        @brief Returns the Shell's OutputBuffer. This is mere placed here to avoid
+               recompiling the entire project when Shell.h changes.
+        @return The OutputBuffer of the Shell
+    */
+    OutputBuffer& OutputHandler::getShellOutputBuffer()
+    {
+        return Shell::getInstance().getOutputBuffer();
+    }
+
+    /**
         @brief Overloaded << operator, redirects the output to the console and the logfile.
         @param sb The streambuffer that should be shown in the console
@@ -96,4 +111,7 @@
             this->logfile_.flush();
         }
+
+        if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Shell) >= this->outputLevel_)
+            Shell::getInstance().getOutputBuffer() << sb;
 
         return *this;
@@ -116,4 +134,7 @@
         }
 
+        if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Shell) >= this->outputLevel_)
+            Shell::getInstance().getOutputBuffer() << manipulator;
+
         return *this;
     }
@@ -134,4 +155,7 @@
             this->logfile_.flush();
         }
+
+        if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Shell) >= this->outputLevel_)
+            Shell::getInstance().getOutputBuffer() << manipulator;
 
         return *this;
@@ -154,4 +178,7 @@
         }
 
+        if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Shell) >= this->outputLevel_)
+            Shell::getInstance().getOutputBuffer() << manipulator;
+
         return *this;
     }
Index: code/trunk/src/core/OutputHandler.h
===================================================================
--- code/trunk/src/core/OutputHandler.h	(revision 1407)
+++ code/trunk/src/core/OutputHandler.h	(revision 1502)
@@ -44,4 +44,6 @@
 #include <string>
 
+#include "OutputBuffer.h"
+
 namespace orxonox
 {
@@ -64,4 +66,20 @@
                 { OutputHandler::getOutStream().setOutputLevel(0); OutputHandler::getOutStream().output(text + "\n"); return text; }
 
+            /** @brief Puts an error on the outstream. @param text The text */
+            static inline std::string error(const std::string& text)
+                { OutputHandler::getOutStream().setOutputLevel(1); OutputHandler::getOutStream().output(text + "\n"); return text; }
+
+            /** @brief Puts a warning on the outstream. @param text The text */
+            static inline std::string warning(const std::string& text)
+                { OutputHandler::getOutStream().setOutputLevel(2); OutputHandler::getOutStream().output(text + "\n"); return text; }
+
+            /** @brief Puts an info on the outstream. @param text The text */
+            static inline std::string info(const std::string& text)
+                { OutputHandler::getOutStream().setOutputLevel(3); OutputHandler::getOutStream().output(text + "\n"); return text; }
+
+            /** @brief Puts some debug output on the outstream. @param text The text */
+            static inline std::string debug(const std::string& text)
+                { OutputHandler::getOutStream().setOutputLevel(4); OutputHandler::getOutStream().output(text + "\n"); return text; }
+
             /** @brief Returns a reference to the logfile. @return The logfile */
             inline std::ofstream& getLogfile()
@@ -77,4 +95,6 @@
 
             static int getSoftDebugLevel(OutputHandler::OutputDevice device);
+
+            OutputBuffer& getShellOutputBuffer();
 
             template <class T>
@@ -138,4 +158,7 @@
         }
 
+        if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Shell) >= this->outputLevel_)
+            OutputHandler::getOutStream().getShellOutputBuffer() << output;
+
         return *this;
     }
@@ -159,4 +182,7 @@
         }
 
+        if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Shell) >= out.getOutputLevel())
+            OutputHandler::getOutStream().getShellOutputBuffer() << output;
+
         return out;
     }
Index: code/trunk/src/core/Script.cc
===================================================================
--- code/trunk/src/core/Script.cc	(revision 1407)
+++ code/trunk/src/core/Script.cc	(revision 1502)
@@ -67,5 +67,6 @@
   {
     output_ += str;
-    COUT(4) << "Lua_output!:" << std::endl << str << std::endl << "***" << std::endl;
+//    COUT(4) << "Lua_output!:" << std::endl << str << std::endl << "***" << std::endl;
+    COUT(5) << str;
   }
 
@@ -99,5 +100,5 @@
 
     if (luaTags) luaSource_ = replaceLuaTags(levelString);
-    COUT(4) << "ParsedSourceCode: " << luaSource_ << std::endl;
+    COUT(5) << "ParsedSourceCode: " << luaSource_ << std::endl;
   }
 
@@ -127,5 +128,8 @@
     if (error == 0)
       error = lua_pcall(luaState_, 0, 0, 0);
-    if (error != 0) COUT(2) << "Error in Lua-script: " << lua_tostring(luaState_, -1) << std::endl;
+    if (error != 0)
+    {
+      COUT(2) << "Error in Lua-script: " << lua_tostring(luaState_, -1) << std::endl;
+    }
   }
 
Index: code/trunk/src/core/Shell.cc
===================================================================
--- code/trunk/src/core/Shell.cc	(revision 1502)
+++ code/trunk/src/core/Shell.cc	(revision 1502)
@@ -0,0 +1,384 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if 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 "Shell.h"
+#include "CommandExecutor.h"
+#include "CoreIncludes.h"
+#include "ConfigValueIncludes.h"
+#include "CoreSettings.h"
+#include "ConsoleCommand.h"
+#include "InputInterfaces.h"
+
+#define SHELL_UPDATE_LISTENERS(function) \
+    for (std::list<ShellListener*>::iterator it = this->listeners_.begin(); it != this->listeners_.end(); ++it) \
+        (*it)->function()
+
+namespace orxonox
+{
+    SetConsoleCommand(Shell, clearShell, true);
+    SetConsoleCommand(Shell, history, true);
+
+    Shell::Shell()
+    {
+        RegisterRootObject(Shell);
+
+        this->scrollPosition_ = 0;
+        this->maxHistoryLength_ = 100;
+        this->historyPosition_ = 0;
+        this->historyOffset_ = 0;
+        this->finishedLastLine_ = true;
+        this->bAddOutputLevel_ = false;
+
+        this->clearLines();
+
+        this->inputBuffer_ = 0;
+        this->setInputBuffer(new InputBuffer());
+
+        this->outputBuffer_.registerListener(this);
+
+        this->setConfigValues();
+    }
+
+    Shell& Shell::createShell()
+    {
+        int level = CoreSettings::getSoftDebugLevel(OutputHandler::LD_Shell);
+        CoreSettings::setSoftDebugLevel(OutputHandler::LD_Shell, -1);
+        static Shell instance;
+        CoreSettings::setSoftDebugLevel(OutputHandler::LD_Shell, level);
+        return instance;
+    }
+
+    Shell& Shell::getInstance()
+    {
+        static Shell& instance = createShell();
+        return instance;
+    }
+
+    void Shell::setConfigValues()
+    {
+        SetConfigValue(maxHistoryLength_, 100);
+        SetConfigValue(historyOffset_, 0);
+        SetConfigValueVector(commandHistory_, std::vector<std::string>());
+
+        if (this->historyOffset_ >= this->maxHistoryLength_)
+            this->historyOffset_ = 0;
+
+        while (this->commandHistory_.size() > this->maxHistoryLength_)
+        {
+            unsigned int index = this->commandHistory_.size() - 1;
+            this->commandHistory_.erase(this->commandHistory_.begin() + index);
+            ModifyConfigValue(commandHistory_, remove, index);
+        }
+    }
+
+    void Shell::setInputBuffer(InputBuffer* buffer)
+    {
+        if (this->inputBuffer_)
+        {
+            this->inputBuffer_->unregisterListener(this);
+            // TODO: may be very dangerous. InputManager already deletes InputBuffer instance!!!
+            delete this->inputBuffer_;
+        }
+
+        this->inputBuffer_ = buffer;
+        this->inputBuffer_->registerListener(this, &Shell::inputChanged, true);
+        this->inputBuffer_->registerListener(this, &Shell::execute, '\r', false);
+        this->inputBuffer_->registerListener(this, &Shell::hintandcomplete, '\t', true);
+        this->inputBuffer_->registerListener(this, &Shell::backspace, '\b', true);
+        this->inputBuffer_->registerListener(this, &Shell::deletechar, KeyCode::Delete);
+        this->inputBuffer_->registerListener(this, &Shell::exit, (char)27, true);
+        this->inputBuffer_->registerListener(this, &Shell::cursor_right, KeyCode::Right);
+        this->inputBuffer_->registerListener(this, &Shell::cursor_left, KeyCode::Left);
+        this->inputBuffer_->registerListener(this, &Shell::cursor_end, KeyCode::End);
+        this->inputBuffer_->registerListener(this, &Shell::cursor_home, KeyCode::Home);
+        this->inputBuffer_->registerListener(this, &Shell::history_up, KeyCode::Up);
+        this->inputBuffer_->registerListener(this, &Shell::history_down, KeyCode::Down);
+        this->inputBuffer_->registerListener(this, &Shell::scroll_up, KeyCode::PageUp);
+        this->inputBuffer_->registerListener(this, &Shell::scroll_down, KeyCode::PageDown);
+    }
+
+    void Shell::clearShell()
+    {
+        Shell::getInstance().clearLines();
+    }
+
+    void Shell::history()
+    {
+        Shell& instance = Shell::getInstance();
+
+        for (int i = instance.historyOffset_; i < (int)instance.commandHistory_.size(); ++i)
+            instance.addLine(instance.commandHistory_[i], -1);
+        for (int i =  0; i < (int)instance.historyOffset_; ++i)
+            instance.addLine(instance.commandHistory_[i], -1);
+    }
+
+    void Shell::registerListener(ShellListener* listener)
+    {
+        this->listeners_.insert(this->listeners_.end(), listener);
+    }
+
+    void Shell::unregisterListener(ShellListener* listener)
+    {
+        for (std::list<ShellListener*>::iterator it = this->listeners_.begin(); it != this->listeners_.end(); )
+        {
+            if ((*it) == listener)
+                this->listeners_.erase(it++);
+            else
+                ++it;
+        }
+    }
+
+    void Shell::setCursorPosition(unsigned int cursor)
+    {
+        this->inputBuffer_->setCursorPosition(cursor);
+        SHELL_UPDATE_LISTENERS(cursorChanged);
+    }
+
+    void Shell::setInput(const std::string& input)
+    {
+        this->inputBuffer_->set(input);
+        this->inputChanged();
+    }
+
+    void Shell::addLine(const std::string& line, int level)
+    {
+        int original_level = OutputHandler::getOutStream().getOutputLevel();
+        OutputHandler::getOutStream().setOutputLevel(level);
+
+        if (!this->finishedLastLine_)
+            this->outputBuffer_ << std::endl;
+
+        this->outputBuffer_ << line << std::endl;
+        OutputHandler::getOutStream().setOutputLevel(original_level);
+    }
+
+    void Shell::clearLines()
+    {
+        this->lines_.clear();
+        this->scrollIterator_ = this->lines_.begin();
+
+        this->scrollPosition_ = 0;
+        this->finishedLastLine_ = true;
+
+        SHELL_UPDATE_LISTENERS(linesChanged);
+    }
+
+    std::list<std::string>::const_iterator Shell::getNewestLineIterator() const
+    {
+        if (this->scrollPosition_)
+            return this->scrollIterator_;
+        else
+            return this->lines_.begin();
+    }
+
+    std::list<std::string>::const_iterator Shell::getEndIterator() const
+    {
+        return this->lines_.end();
+    }
+
+    void Shell::addToHistory(const std::string& command)
+    {
+        ModifyConfigValue(commandHistory_, set, this->historyOffset_, command);
+        this->historyPosition_ = 0;
+        ModifyConfigValue(historyOffset_, set, (this->historyOffset_ + 1) % this->maxHistoryLength_);
+    }
+
+    std::string Shell::getFromHistory() const
+    {
+        unsigned int index = mod(((int)this->historyOffset_) - ((int)this->historyPosition_), this->maxHistoryLength_);
+        if (index < this->commandHistory_.size() && this->historyPosition_ != 0)
+            return this->commandHistory_[index];
+        else
+            return "";
+    }
+
+    void Shell::outputChanged()
+    {
+        std::string output;
+        bool newline;
+        do
+        {
+            newline = this->outputBuffer_.getLine(&output);
+
+            if (!newline && output == "")
+                break;
+
+            if (this->finishedLastLine_)
+            {
+                if (this->bAddOutputLevel_)
+                    output.insert(0, 1, (char)OutputHandler::getOutStream().getOutputLevel());
+
+                this->lines_.insert(this->lines_.begin(), output);
+
+                if (this->scrollPosition_)
+                    this->scrollPosition_++;
+                else
+                    this->scrollIterator_ = this->lines_.begin();
+
+                this->finishedLastLine_ = newline;
+
+                if (!this->scrollPosition_)
+                {
+                    SHELL_UPDATE_LISTENERS(lineAdded);
+                }
+            }
+            else
+            {
+                (*this->lines_.begin()) += output;
+                this->finishedLastLine_ = newline;
+                SHELL_UPDATE_LISTENERS(onlyLastLineChanged);
+            }
+
+        } while (newline);
+    }
+
+    void Shell::inputChanged()
+    {
+        SHELL_UPDATE_LISTENERS(inputChanged);
+        SHELL_UPDATE_LISTENERS(cursorChanged);
+    }
+
+    void Shell::execute()
+    {
+        this->addToHistory(this->inputBuffer_->get());
+        this->addLine(this->inputBuffer_->get(), 0);
+
+        if (!CommandExecutor::execute(this->inputBuffer_->get()))
+            this->addLine("Error: Can't execute \"" + this->inputBuffer_->get() + "\".", 1);
+
+        this->clear();
+    }
+
+    void Shell::hintandcomplete()
+    {
+        this->inputBuffer_->set(CommandExecutor::complete(this->inputBuffer_->get()));
+        this->addLine(CommandExecutor::hint(this->inputBuffer_->get()), -1);
+
+        this->inputChanged();
+    }
+
+    void Shell::backspace()
+    {
+        this->inputBuffer_->removeBehindCursor();
+        SHELL_UPDATE_LISTENERS(inputChanged);
+        SHELL_UPDATE_LISTENERS(cursorChanged);
+    }
+
+    void Shell::deletechar()
+    {
+        this->inputBuffer_->removeAtCursor();
+        SHELL_UPDATE_LISTENERS(inputChanged);
+    }
+
+    void Shell::clear()
+    {
+        this->inputBuffer_->clear();
+        this->historyPosition_ = 0;
+        SHELL_UPDATE_LISTENERS(inputChanged);
+        SHELL_UPDATE_LISTENERS(cursorChanged);
+    }
+
+    void Shell::cursor_right()
+    {
+        this->inputBuffer_->increaseCursor();
+        SHELL_UPDATE_LISTENERS(cursorChanged);
+    }
+
+    void Shell::cursor_left()
+    {
+        this->inputBuffer_->decreaseCursor();
+        SHELL_UPDATE_LISTENERS(cursorChanged);
+    }
+
+    void Shell::cursor_end()
+    {
+        this->inputBuffer_->setCursorToEnd();
+        SHELL_UPDATE_LISTENERS(cursorChanged);
+    }
+
+    void Shell::cursor_home()
+    {
+        this->inputBuffer_->setCursorToBegin();
+        SHELL_UPDATE_LISTENERS(cursorChanged);
+    }
+
+    void Shell::history_up()
+    {
+        if (this->historyPosition_ < this->commandHistory_.size())
+        {
+            this->historyPosition_++;
+            this->inputBuffer_->set(this->getFromHistory());
+        }
+    }
+
+    void Shell::history_down()
+    {
+        if (this->historyPosition_ > 0)
+        {
+            this->historyPosition_--;
+            this->inputBuffer_->set(this->getFromHistory());
+        }
+    }
+
+    void Shell::scroll_up()
+    {
+        if (this->scrollIterator_ != this->lines_.end())
+        {
+            ++this->scrollIterator_;
+            ++this->scrollPosition_;
+
+            SHELL_UPDATE_LISTENERS(linesChanged);
+        }
+    }
+
+    void Shell::scroll_down()
+    {
+        if (this->scrollIterator_ != this->lines_.begin())
+        {
+            --this->scrollIterator_;
+            --this->scrollPosition_;
+
+            SHELL_UPDATE_LISTENERS(linesChanged);
+        }
+    }
+
+    void Shell::exit()
+    {
+        if (this->inputBuffer_->getSize() > 0)
+        {
+            this->clear();
+            return;
+        }
+
+        this->clear();
+        this->scrollPosition_ = 0;
+        this->scrollIterator_ = this->lines_.begin();
+
+        SHELL_UPDATE_LISTENERS(exit);
+    }
+}
Index: code/trunk/src/core/Shell.h
===================================================================
--- code/trunk/src/core/Shell.h	(revision 1502)
+++ code/trunk/src/core/Shell.h	(revision 1502)
@@ -0,0 +1,144 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if 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 _Shell_H__
+#define _Shell_H__
+
+#include <list>
+#include <vector>
+
+#include "CorePrereqs.h"
+
+#include "OrxonoxClass.h"
+#include "InputBuffer.h"
+#include "OutputBuffer.h"
+
+namespace orxonox
+{
+    class _CoreExport ShellListener
+    {
+        friend class Shell;
+
+        public:
+            virtual ~ShellListener() {}
+
+        private:
+            virtual void linesChanged() {}
+            virtual void onlyLastLineChanged() {}
+            virtual void lineAdded() {}
+            virtual void inputChanged() {}
+            virtual void cursorChanged() {}
+            virtual void exit() {}
+    };
+
+    class _CoreExport Shell : virtual public OrxonoxClass, public OutputBufferListener
+    {
+        public:
+            static Shell& getInstance();
+            static Shell& createShell();
+
+            static void clearShell();
+            static void history();
+
+            virtual void setConfigValues();
+
+            void registerListener(ShellListener* listener);
+            void unregisterListener(ShellListener* listener);
+
+            void setInputBuffer(InputBuffer* buffer);
+            inline InputBuffer& getInputBuffer()
+                { return (*this->inputBuffer_); }
+            inline OutputBuffer& getOutputBuffer()
+                { return this->outputBuffer_; }
+
+            void setCursorPosition(unsigned int cursor);
+            inline unsigned int getCursorPosition() const
+                { return this->inputBuffer_->getCursorPosition(); }
+
+            void setInput(const std::string& input);
+
+            inline void clearInput()
+                { this->setInput(""); }
+            inline std::string getInput() const
+                { return this->inputBuffer_->get(); }
+
+            std::list<std::string>::const_iterator getNewestLineIterator() const;
+            std::list<std::string>::const_iterator getEndIterator() const;
+
+            void addLine(const std::string& line, int level = 0);
+            void clearLines();
+
+            inline unsigned int getNumLines() const
+                { return this->lines_.size(); }
+            inline unsigned int getScrollPosition() const
+                { return this->scrollPosition_; }
+
+            inline void addOutputLevel(bool bAddOutputLevel)
+                { this->bAddOutputLevel_ = bAddOutputLevel; }
+
+        private:
+            Shell();
+            Shell(const Shell& other);
+            virtual ~Shell() {}
+
+            void addToHistory(const std::string& command);
+            std::string getFromHistory() const;
+
+            virtual void outputChanged();
+            void inputChanged();
+            void execute();
+            void hintandcomplete();
+            void backspace();
+            void deletechar();
+            void clear();
+            void cursor_right();
+            void cursor_left();
+            void cursor_end();
+            void cursor_home();
+            void history_up();
+            void history_down();
+            void scroll_up();
+            void scroll_down();
+            void exit();
+
+            std::list<ShellListener*> listeners_;
+            InputBuffer* inputBuffer_;
+            OutputBuffer outputBuffer_;
+            bool finishedLastLine_;
+            std::list<std::string> lines_;
+            std::list<std::string>::const_iterator scrollIterator_;
+            unsigned int scrollPosition_;
+            std::vector<std::string> commandHistory_;
+            unsigned int maxHistoryLength_;
+            unsigned int historyPosition_;
+            unsigned int historyOffset_;
+            bool bAddOutputLevel_;
+    };
+}
+
+#endif /* _Shell_H__ */
Index: code/trunk/src/core/TclBind.cc
===================================================================
--- code/trunk/src/core/TclBind.cc	(revision 1407)
+++ code/trunk/src/core/TclBind.cc	(revision 1502)
@@ -33,9 +33,12 @@
 #include "CommandExecutor.h"
 #include "Debug.h"
+#include "TclThreadManager.h"
 #include "TclBind.h"
+#include "util/String.h"
 
 namespace orxonox
 {
-    ConsoleCommandShortcutGeneric(tcl, createExecutor(createFunctor(&TclBind::tcl), "tcl", AccessLevel::None));
+    SetConsoleCommandShortcutGeneric(tcl, createConsoleCommand(createFunctor(&TclBind::tcl), "tcl"));
+    SetConsoleCommandShortcutGeneric(bgerror, createConsoleCommand(createFunctor(&TclBind::bgerror), "bgerror"));
 
     TclBind::TclBind()
@@ -59,5 +62,5 @@
     void TclBind::setDataPath(const std::string& datapath)
     {
-        this->tclLibPath_ = datapath + "/tcl";
+        this->tclLibPath_ = datapath + "/tcl" + TCL_VERSION + "/";
         this->bSetTclLibPath_ = true;
 
@@ -70,9 +73,20 @@
         {
             this->interpreter_ = new Tcl::interpreter(this->tclLibPath_);
-            this->interpreter_->def("puts", TclBind::puts, Tcl::variadic());
-            this->interpreter_->def("orxonox", TclBind::orxonox, Tcl::variadic());
-            this->interpreter_->def("execute", TclBind::execute, Tcl::variadic());
-            this->interpreter_->eval("proc unknown {args} { return [orxonox $args] }");
-            this->interpreter_->eval("rename exit tclexit; proc exit {} { orxonox exit }");
+            this->interpreter_->def("orxonox::query", TclBind::tcl_query, Tcl::variadic());
+            this->interpreter_->def("orxonox::crossquery", TclThreadManager::tcl_crossquery, Tcl::variadic());
+            this->interpreter_->def("execute", TclBind::tcl_execute, Tcl::variadic());
+
+            try
+            {
+                this->interpreter_->eval("proc query args { orxonox::query $args }");
+                this->interpreter_->eval("proc crossquery {id args} { orxonox::crossquery 0 $id $args }");
+                this->interpreter_->eval("set id 0");
+                this->interpreter_->eval("rename exit tcl::exit; proc exit {} { execute exit }");
+                this->interpreter_->eval("redef_puts");
+            }
+            catch (Tcl::tcl_error const &e)
+            {   COUT(1) << "Tcl error while creating Tcl-interpreter: " << e.what() << std::endl;   }
+            catch (std::exception const &e)
+            {   COUT(1) << "Error while creating Tcl-interpreter: " << e.what() << std::endl;   }
         }
     }
@@ -89,19 +103,14 @@
     }
 
-    void TclBind::puts(Tcl::object const &args)
+    std::string TclBind::tcl_query(Tcl::object const &args)
     {
-        COUT(0) << args.get() << std::endl;
-    }
+        COUT(4) << "Tcl_query: " << args.get() << std::endl;
 
-    std::string TclBind::orxonox(Tcl::object const &args)
-    {
-std::cout << "Tcl_execute: args: " << args.get() << std::endl;
-        std::string command = args.get();
-
-        if (command.size() >= 2 && command[0] == '{' && command[command.size() - 1] == '}')
-            command = command.substr(1, command.size() - 2);
+        std::string command = stripEnclosingBraces(args.get());
 
         if (!CommandExecutor::execute(command, false))
+        {
             COUT(1) << "Error: Can't execute command \"" << command << "\"!" << std::endl;
+        }
 
         if (CommandExecutor::getLastEvaluation().hasReturnvalue())
@@ -111,27 +120,40 @@
     }
 
-    void TclBind::execute(Tcl::object const &args)
+    void TclBind::tcl_execute(Tcl::object const &args)
     {
+        COUT(4) << "Tcl_execute: " << args.get() << std::endl;
+        std::string command = stripEnclosingBraces(args.get());
+
+        if (!CommandExecutor::execute(command, false))
+        {
+            COUT(1) << "Error: Can't execute command \"" << command << "\"!" << std::endl;
+        }
     }
 
     std::string TclBind::tcl(const std::string& tclcode)
     {
-        try
+        if (TclBind::getInstance().interpreter_)
         {
-            std::string output = TclBind::getInstance().interpreter_->eval(tclcode);
-            if (output != "")
-                COUT(0) << "tcl> " << output << std::endl;
-            return output;
-        }
-        catch (Tcl::tcl_error const &e)
-        {
-            COUT(1) << "tcl> Error: " << e.what() << std::endl;
-        }
-        catch (std::exception const &e)
-        {
-            COUT(1) << "Error while executing tcl: " << e.what() << std::endl;
+            try
+            {
+                std::string output = TclBind::getInstance().interpreter_->eval(tclcode);
+                if (output != "")
+                {
+                    COUT(0) << "tcl> " << output << std::endl;
+                }
+                return output;
+            }
+            catch (Tcl::tcl_error const &e)
+            {   COUT(1) << "tcl> Error: " << e.what() << std::endl;   }
+            catch (std::exception const &e)
+            {   COUT(1) << "Error while executing Tcl: " << e.what() << std::endl;   }
         }
 
         return "";
+    }
+
+    void TclBind::bgerror(std::string error)
+    {
+        COUT(1) << "Tcl background error: " << stripEnclosingBraces(error) << std::endl;
     }
 
@@ -144,11 +166,7 @@
         }
         catch (Tcl::tcl_error const &e)
-        {
-            COUT(1) << "Error: " << e.what() << std::endl;
-        }
+        {   COUT(1) << "Tcl error: " << e.what() << std::endl;   }
         catch (std::exception const &e)
-        {
-            COUT(1) << "Error while executing tcl: " << e.what() << std::endl;
-        }
+        {   COUT(1) << "Error while executing Tcl: " << e.what() << std::endl;   }
 
         return false;
Index: code/trunk/src/core/TclBind.h
===================================================================
--- code/trunk/src/core/TclBind.h	(revision 1407)
+++ code/trunk/src/core/TclBind.h	(revision 1502)
@@ -41,12 +41,16 @@
             static TclBind& getInstance();
 
+            static std::string tcl(const std::string& tclcode);
+            static void bgerror(std::string error);
+
             void setDataPath(const std::string& datapath);
+            std::string getTclLibPath() const { return this->tclLibPath_; }
             void createTclInterpreter();
             void createNewTclInterpreter();
+            Tcl::interpreter* getTclInterpreter() const { return this->interpreter_; }
 
-            static void puts(Tcl::object const &args);
-            static void execute(Tcl::object const &args);
-            static std::string orxonox(Tcl::object const &args);
-            static std::string tcl(const std::string& tclcode);
+            static std::string tcl_query(Tcl::object const &args);
+            static void tcl_execute(Tcl::object const &args);
+
             static bool eval(const std::string& tclcode);
 
Index: code/trunk/src/core/TclThreadManager.cc
===================================================================
--- code/trunk/src/core/TclThreadManager.cc	(revision 1502)
+++ code/trunk/src/core/TclThreadManager.cc	(revision 1502)
@@ -0,0 +1,668 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if 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 <iostream>
+#include <string>
+
+#include <boost/thread/thread.hpp>
+#include <boost/bind.hpp>
+
+#include <OgreTimer.h>
+
+#include "CoreIncludes.h"
+#include "ConsoleCommand.h"
+#include "CommandExecutor.h"
+#include "Debug.h"
+#include "TclBind.h"
+#include "TclThreadManager.h"
+#include "util/Convert.h"
+
+#define TCLTHREADMANAGER_MAX_QUEUE_LENGTH 100
+#define TCLTHREADMANAGER_MAX_CPU_USAGE 0.50
+
+namespace orxonox
+{
+    SetConsoleCommandShortcutGeneric(tclexecute, createConsoleCommand(createFunctor(&TclThreadManager::execute), "tclexecute")).setArgumentCompleter(0, autocompletion::tclthreads());
+    SetConsoleCommandShortcutGeneric(tclquery,   createConsoleCommand(createFunctor(&TclThreadManager::query),   "tclquery"  )).setArgumentCompleter(0, autocompletion::tclthreads());
+    SetConsoleCommand(TclThreadManager, create,  false);
+    SetConsoleCommand(TclThreadManager, destroy, false).setArgumentCompleter(0, autocompletion::tclthreads());
+    SetConsoleCommand(TclThreadManager, execute, false).setArgumentCompleter(0, autocompletion::tclthreads());
+    SetConsoleCommand(TclThreadManager, query,   false).setArgumentCompleter(0, autocompletion::tclthreads());
+    SetConsoleCommand(TclThreadManager, status,  false);
+    SetConsoleCommand(TclThreadManager, dump,    false).setArgumentCompleter(0, autocompletion::tclthreads());
+    SetConsoleCommand(TclThreadManager, flush,   false).setArgumentCompleter(0, autocompletion::tclthreads());
+
+    TclThreadManager* instance_tclthreadmanager = &TclThreadManager::getInstance();
+
+    TclThreadManager::TclThreadManager()
+    {
+        RegisterRootObject(TclThreadManager);
+
+        this->threadCounter_ = 0;
+        this->orxonoxInterpreterBundle_.id_ = 0;
+        this->orxonoxInterpreterBundle_.interpreter_ = TclBind::getInstance().getTclInterpreter();
+#if (BOOST_VERSION >= 103500)
+        this->threadID_ = boost::this_thread::get_id();
+#else
+        //
+#endif
+    }
+
+    TclThreadManager& TclThreadManager::getInstance()
+    {
+        static TclThreadManager instance;
+        return instance;
+    }
+
+    unsigned int TclThreadManager::create()
+    {
+        boost::mutex::scoped_lock bundles_lock(TclThreadManager::getInstance().bundlesMutex_);
+        TclThreadManager::getInstance().threadCounter_++;
+        std::string name = getConvertedValue<unsigned int, std::string>(TclThreadManager::getInstance().threadCounter_);
+
+        TclInterpreterBundle* bundle = new TclInterpreterBundle;
+        bundle->id_ = TclThreadManager::getInstance().threadCounter_;
+        bundle->interpreter_ = TclThreadManager::getInstance().createNewTclInterpreter(name);
+        bundle->interpreterName_ = name;
+        bundle->running_ = true;
+        bundle->finished_ = true;
+
+        TclThreadManager::getInstance().interpreterBundles_[TclThreadManager::getInstance().threadCounter_] = bundle;
+        COUT(0) << "Created new Tcl-interpreter with ID " << TclThreadManager::getInstance().threadCounter_ << std::endl;
+        return TclThreadManager::getInstance().threadCounter_;
+    }
+
+    unsigned int TclThreadManager::createID(unsigned int threadID)
+    {
+        unsigned int temp = TclThreadManager::getInstance().threadCounter_;
+        TclThreadManager::getInstance().threadCounter_ = threadID - 1;
+        TclThreadManager::create();
+        TclThreadManager::getInstance().threadCounter_ = temp;
+        return threadID;
+    }
+
+    void TclThreadManager::destroy(unsigned int threadID)
+    {
+        TclInterpreterBundle* bundle = TclThreadManager::getInstance().getInterpreterBundle(threadID);
+        if (bundle)
+        {
+            {
+                boost::mutex::scoped_lock running_lock(bundle->runningMutex_);
+                bundle->running_ = false;
+            }
+            while (true)
+            {
+                {
+                    boost::mutex::scoped_lock finished_lock(bundle->finishedMutex_);
+                    if (bundle->finished_)
+                    {
+                        boost::mutex::scoped_lock bundles_lock(TclThreadManager::getInstance().bundlesMutex_);
+#if (BOOST_VERSION >= 103500)
+                        boost::mutex::scoped_try_lock interpreter_lock(bundle->interpreterMutex_);
+#else
+                        boost::try_mutex::scoped_try_lock interpreter_lock(bundle->interpreterMutex_);
+#endif
+                        try
+                        {
+                            while (!interpreter_lock.try_lock())
+                            {
+                                TclThreadManager::getInstance().orxonoxEvalCondition_.notify_one();
+#if (BOOST_VERSION >= 103500)
+                                boost::this_thread::yield();
+#else
+                                boost::thread::yield();
+#endif
+                            }
+                        } catch (...) {}
+                        delete bundle->interpreter_;
+                        delete bundle;
+                        TclThreadManager::getInstance().interpreterBundles_.erase(threadID);
+                        break;
+                    }
+                }
+
+                TclThreadManager::getInstance().orxonoxEvalCondition_.notify_one();
+#if (BOOST_VERSION >= 103500)
+                boost::this_thread::yield();
+#else
+                boost::thread::yield();
+#endif
+            }
+
+            COUT(0) << "Destroyed Tcl-interpreter with ID " << threadID << std::endl;
+        }
+    }
+
+    void TclThreadManager::execute(unsigned int threadID, const std::string& _command)
+    {
+        std::string command = stripEnclosingBraces(_command);
+
+        if (threadID == 0)
+            TclThreadManager::getInstance().pushCommandToQueue(command);
+        else
+            TclThreadManager::getInstance().pushCommandToQueue(threadID, command);
+    }
+
+    std::string TclThreadManager::query(unsigned int threadID, const std::string& command)
+    {
+        return TclThreadManager::getInstance().evalQuery(TclThreadManager::getInstance().orxonoxInterpreterBundle_.id_, threadID, command);
+    }
+
+    void TclThreadManager::status()
+    {
+        COUT(0) << "Thread ID" << '\t' << "Queue size" << '\t' << "State" << std::endl;
+
+        std::string output = "Orxonox";
+        output += "\t\t";
+        {
+            boost::mutex::scoped_lock queue_lock(TclThreadManager::getInstance().orxonoxInterpreterBundle_.queueMutex_);
+            output += getConvertedValue<unsigned int, std::string>(TclThreadManager::getInstance().orxonoxInterpreterBundle_.queue_.size());
+        }
+        output += "\t\t";
+        output += "busy";
+        COUT(0) << output << std::endl;
+
+        boost::mutex::scoped_lock bundles_lock(TclThreadManager::getInstance().bundlesMutex_);
+        for (std::map<unsigned int, TclInterpreterBundle*>::const_iterator it = TclThreadManager::getInstance().interpreterBundles_.begin(); it != TclThreadManager::getInstance().interpreterBundles_.end(); ++it)
+        {
+            std::string output = getConvertedValue<unsigned int, std::string>((*it).first);
+            output += "\t\t";
+            {
+                boost::mutex::scoped_lock queue_lock((*it).second->queueMutex_);
+                output += getConvertedValue<unsigned int, std::string>((*it).second->queue_.size());
+            }
+            output += "\t\t";
+            {
+#if (BOOST_VERSION >= 103500)
+                boost::mutex::scoped_try_lock interpreter_lock((*it).second->interpreterMutex_);
+#else
+                boost::try_mutex::scoped_try_lock interpreter_lock((*it).second->interpreterMutex_);
+#endif
+                if (interpreter_lock.try_lock())
+                    output += "ready";
+                else
+                    output += "busy";
+            }
+            COUT(0) << output << std::endl;
+        }
+    }
+
+    void TclThreadManager::dump(unsigned int threadID)
+    {
+        TclInterpreterBundle* bundle = 0;
+        if (threadID == 0)
+        {
+            bundle = &TclThreadManager::getInstance().orxonoxInterpreterBundle_;
+            COUT(0) << "Queue dump of Orxonox:" << std::endl;
+        }
+        else
+        {
+            if ((bundle = TclThreadManager::getInstance().getInterpreterBundle(threadID)))
+            {
+                COUT(0) << "Queue dump of Tcl-thread " << threadID << ":" << std::endl;
+            }
+            else
+                return;
+        }
+
+        boost::mutex::scoped_lock queue_lock(bundle->queueMutex_);
+        unsigned int index = 0;
+        for (std::list<std::string>::const_iterator it = bundle->queue_.begin(); it != bundle->queue_.end(); ++it)
+        {
+            index++;
+            COUT(0) << index << ": " << (*it) << std::endl;
+        }
+    }
+
+    void TclThreadManager::flush(unsigned int threadID)
+    {
+        TclInterpreterBundle* bundle = 0;
+        if (threadID == 0)
+            bundle = &TclThreadManager::getInstance().orxonoxInterpreterBundle_;
+        else
+            if (!(bundle = TclThreadManager::getInstance().getInterpreterBundle(threadID)))
+                return;
+
+        boost::mutex::scoped_lock queue_lock(bundle->queueMutex_);
+        bundle->queue_.clear();
+        if (threadID == 0)
+        {
+            COUT(0) << "Flushed queue of Orxonox Tcl-interpreter." << std::endl;
+        }
+        else
+        {
+            COUT(0) << "Flushed queue of Tcl-interpreter " << threadID << "." << std::endl;
+        }
+    }
+
+    void TclThreadManager::tcl_execute(Tcl::object const &args)
+    {
+        TclThreadManager::getInstance().pushCommandToQueue(stripEnclosingBraces(args.get()));
+    }
+
+    std::string TclThreadManager::tcl_query(int querierID, Tcl::object const &args)
+    {
+        return TclThreadManager::getInstance().evalQuery((unsigned int)querierID, stripEnclosingBraces(args.get()));
+    }
+
+    std::string TclThreadManager::tcl_crossquery(int querierID, int threadID, Tcl::object const &args)
+    {
+        return TclThreadManager::getInstance().evalQuery((unsigned int)querierID, (unsigned int)threadID, stripEnclosingBraces(args.get()));
+    }
+
+    bool TclThreadManager::tcl_running(int threadID)
+    {
+        TclInterpreterBundle* bundle = TclThreadManager::getInstance().getInterpreterBundle((unsigned int)threadID);
+        if (bundle)
+        {
+            boost::mutex::scoped_lock running_lock(bundle->runningMutex_);
+            return bundle->running_;
+        }
+        return false;
+    }
+
+    Tcl::interpreter* TclThreadManager::createNewTclInterpreter(const std::string& threadID)
+    {
+        Tcl::interpreter* i = 0;
+        i = new Tcl::interpreter(TclBind::getInstance().getTclLibPath());
+
+        try
+        {
+            i->def("orxonox::query", TclThreadManager::tcl_query, Tcl::variadic());
+            i->def("orxonox::crossquery", TclThreadManager::tcl_crossquery, Tcl::variadic());
+            i->def("orxonox::execute", TclThreadManager::tcl_execute, Tcl::variadic());
+            i->def("orxonox::running", TclThreadManager::tcl_running);
+
+            i->def("execute", TclThreadManager::tcl_execute, Tcl::variadic());
+            i->eval("proc query args { orxonox::query " + threadID + " $args }");
+            i->eval("proc crossquery {id args} { orxonox::crossquery " + threadID + " $id $args }");
+            i->eval("set id " + threadID);
+
+            i->eval("rename exit tcl::exit");
+            i->eval("proc exit {} { orxonox TclThreadManager destroy " + threadID + " }");
+
+            i->eval("redef_puts");
+
+//            i->eval("rename while tcl::while");
+//            i->eval("proc while {test command} { tcl::while {[uplevel 1 expr $test]} {uplevel 1 $command} }"); // (\"$test\" && [orxonox::running " + threadID + "]])
+//            i->eval("rename for tcl::for");
+//            i->eval("proc for {start test next command} { uplevel tcl::for \"$start\" \"$test\" \"$next\" \"$command\" }");
+        }
+        catch (Tcl::tcl_error const &e)
+        {   COUT(1) << "Tcl error while creating Tcl-interpreter (" << threadID << "): " << e.what() << std::endl;   }
+        catch (std::exception const &e)
+        {   COUT(1) << "Error while creating Tcl-interpreter (" << threadID << "): " << e.what() << std::endl;   }
+
+        return i;
+    }
+
+    TclInterpreterBundle* TclThreadManager::getInterpreterBundle(unsigned int threadID)
+    {
+        boost::mutex::scoped_lock bundles_lock(this->bundlesMutex_);
+        std::map<unsigned int, TclInterpreterBundle*>::iterator it = this->interpreterBundles_.find(threadID);
+        if (it != this->interpreterBundles_.end())
+        {
+            return (*it).second;
+        }
+        else
+        {
+            this->error("Error: No Tcl-interpreter with ID " + getConvertedValue<unsigned int, std::string>(threadID) + " existing.");
+            return 0;
+        }
+    }
+
+    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 += getConvertedValue<unsigned int, std::string>(*it);
+        }
+        return output;
+    }
+
+    void TclThreadManager::error(const std::string& error)
+    {
+#if (BOOST_VERSION >= 103500)
+        if (boost::this_thread::get_id() != this->threadID_)
+#else
+        if (boost::thread() != this->threadID_)
+#endif
+        {
+            boost::mutex::scoped_lock queue_lock(this->orxonoxInterpreterBundle_.queueMutex_);
+            if (this->orxonoxInterpreterBundle_.queue_.size() >= TCLTHREADMANAGER_MAX_QUEUE_LENGTH)
+            {
+#if (BOOST_VERSION >= 103500)
+                boost::this_thread::yield();
+#else
+                boost::thread::yield();
+#endif
+                return;
+            }
+        }
+
+        this->forceCommandToFrontOfQueue("error " + error);
+    }
+
+    void TclThreadManager::debug(const std::string& error)
+    {
+#if (BOOST_VERSION >= 103500)
+        if (boost::this_thread::get_id() != this->threadID_)
+#else
+        if (boost::thread() != this->threadID_)
+#endif
+        {
+            boost::mutex::scoped_lock queue_lock(this->orxonoxInterpreterBundle_.queueMutex_);
+            if (this->orxonoxInterpreterBundle_.queue_.size() >= TCLTHREADMANAGER_MAX_QUEUE_LENGTH)
+            {
+#if (BOOST_VERSION >= 103500)
+                boost::this_thread::yield();
+#else
+                boost::thread::yield();
+#endif
+                return;
+            }
+        }
+
+        this->forceCommandToFrontOfQueue("debug " + error);
+    }
+
+    void TclThreadManager::pushCommandToQueue(const std::string& command)
+    {
+        boost::mutex::scoped_lock queue_lock(this->orxonoxInterpreterBundle_.queueMutex_);
+        while (this->orxonoxInterpreterBundle_.queue_.size() >= TCLTHREADMANAGER_MAX_QUEUE_LENGTH)
+            this->fullQueueCondition_.wait(queue_lock);
+
+        this->orxonoxInterpreterBundle_.queue_.push_back(command);
+    }
+
+    void TclThreadManager::forceCommandToFrontOfQueue(const std::string& command)
+    {
+        boost::mutex::scoped_lock queue_lock(this->orxonoxInterpreterBundle_.queueMutex_);
+        this->orxonoxInterpreterBundle_.queue_.push_front(command);
+    }
+
+    std::string TclThreadManager::popCommandFromQueue()
+    {
+        boost::mutex::scoped_lock queue_lock(this->orxonoxInterpreterBundle_.queueMutex_);
+        std::string temp = this->orxonoxInterpreterBundle_.queue_.front();
+        this->orxonoxInterpreterBundle_.queue_.pop_front();
+        this->fullQueueCondition_.notify_one();
+        return temp;
+    }
+
+    bool TclThreadManager::queueIsEmpty()
+    {
+        boost::mutex::scoped_lock queue_lock(this->orxonoxInterpreterBundle_.queueMutex_);
+        return this->orxonoxInterpreterBundle_.queue_.empty();
+    }
+
+    void TclThreadManager::pushCommandToQueue(unsigned int threadID, const std::string& command)
+    {
+        TclInterpreterBundle* bundle = this->getInterpreterBundle(threadID);
+        if (bundle)
+        {
+            boost::mutex::scoped_lock queue_lock(bundle->queueMutex_);
+            if (bundle->queue_.size() >= TCLTHREADMANAGER_MAX_QUEUE_LENGTH)
+            {
+                this->error("Error: Queue of Tcl-interpreter " + getConvertedValue<unsigned int, std::string>(threadID) + " is full, couldn't add command.");
+                return;
+            }
+
+            bundle->queue_.push_back(command);
+        }
+    }
+
+    std::string TclThreadManager::popCommandFromQueue(unsigned int threadID)
+    {
+        TclInterpreterBundle* bundle = this->getInterpreterBundle(threadID);
+        if (bundle)
+        {
+            boost::mutex::scoped_lock queue_lock(bundle->queueMutex_);
+            std::string temp = bundle->queue_.front();
+            bundle->queue_.pop_front();
+            return temp;
+        }
+        return "";
+    }
+
+    bool TclThreadManager::queueIsEmpty(unsigned int threadID)
+    {
+        TclInterpreterBundle* bundle = this->getInterpreterBundle(threadID);
+        if (bundle)
+        {
+            boost::mutex::scoped_lock queue_lock(bundle->queueMutex_);
+            return bundle->queue_.empty();
+        }
+        return true;
+    }
+
+    bool TclThreadManager::updateQueriersList(TclInterpreterBundle* querier, TclInterpreterBundle* target)
+    {
+        if (querier == target)
+            return false;
+
+        boost::mutex::scoped_lock queriers_lock(target->queriersMutex_);
+
+        {
+            boost::mutex::scoped_lock queriers_lock(querier->queriersMutex_);
+            target->queriers_.insert(target->queriers_.end(), querier->queriers_.begin(), querier->queriers_.end());
+        }
+
+        target->queriers_.insert(target->queriers_.end(), querier->id_);
+
+        if (std::find(target->queriers_.begin(), target->queriers_.end(), target->id_) != target->queriers_.end())
+        {
+            this->error("Error: Circular query (" + this->dumpList(target->queriers_) + " -> " + getConvertedValue<unsigned int, std::string>(target->id_) + "), couldn't query Tcl-interpreter with ID " + getConvertedValue<unsigned int, std::string>(target->id_) + " from other interpreter with ID " + getConvertedValue<unsigned int, std::string>(querier->id_) + ".");
+            return false;
+        }
+
+        return true;
+    }
+
+    std::string TclThreadManager::evalQuery(unsigned int querierID, const std::string& command)
+    {
+        TclInterpreterBundle* querier = this->getInterpreterBundle(querierID);
+        std::string output = "";
+        if (querier)
+        {
+            if (this->updateQueriersList(querier, &this->orxonoxInterpreterBundle_))
+            {
+#if (BOOST_VERSION >= 103500)
+                boost::mutex::scoped_lock interpreter_lock(this->orxonoxInterpreterBundle_.interpreterMutex_);
+#else
+                boost::try_mutex::scoped_lock interpreter_lock(this->orxonoxInterpreterBundle_.interpreterMutex_);
+#endif
+                this->orxonoxEvalCondition_.wait(interpreter_lock);
+
+                if (!CommandExecutor::execute(command, false))
+                    this->error("Error: Can't execute command \"" + command + "\"!");
+
+                if (CommandExecutor::getLastEvaluation().hasReturnvalue())
+                    output = CommandExecutor::getLastEvaluation().getReturnvalue().toString();
+            }
+
+            boost::mutex::scoped_lock queriers_lock(this->orxonoxInterpreterBundle_.queriersMutex_);
+            this->orxonoxInterpreterBundle_.queriers_.clear();
+        }
+        return output;
+    }
+
+    std::string TclThreadManager::evalQuery(unsigned int querierID, unsigned int threadID, const std::string& command)
+    {
+        TclInterpreterBundle* target = 0;
+        if (threadID)
+            target = this->getInterpreterBundle(threadID);
+        else
+            target = &this->orxonoxInterpreterBundle_;
+
+        std::string output = "";
+        if (target)
+        {
+            TclInterpreterBundle* querier = 0;
+            if (querierID)
+                querier = this->getInterpreterBundle(querierID);
+            else
+                querier = &this->orxonoxInterpreterBundle_;
+
+            if (querier)
+            {
+                if (this->updateQueriersList(querier, target))
+                {
+#if (BOOST_VERSION >= 103500)
+                    boost::mutex::scoped_try_lock interpreter_lock(target->interpreterMutex_);
+#else
+                    boost::try_mutex::scoped_try_lock interpreter_lock(target->interpreterMutex_);
+#endif
+                    bool successfullyLocked = false;
+                    try
+                    {
+                        if (querierID == 0 || std::find(querier->queriers_.begin(), querier->queriers_.end(), (unsigned int)0) != querier->queriers_.end())
+                            successfullyLocked = interpreter_lock.try_lock();
+                        else
+                        {
+                            while (!interpreter_lock.try_lock())
+                            {
+#if (BOOST_VERSION >= 103500)
+                                boost::this_thread::yield();
+#else
+                                boost::thread::yield();
+#endif
+                            }
+
+                            successfullyLocked = true;
+                        }
+                    } catch (...) {}
+
+                    if (successfullyLocked)
+                    {
+                        this->debug("TclThread_query: " + command);
+                        try
+                        {   output = (std::string)target->interpreter_->eval(command);   }
+                        catch (Tcl::tcl_error const &e)
+                        {   this->error("Tcl error: " + (std::string)e.what());   }
+                        catch (std::exception const &e)
+                        {   this->error("Error while executing Tcl: " + (std::string)e.what());   }
+                    }
+                    else
+                    {
+                        this->error("Error: Couldn't query Tcl-interpreter with ID " + getConvertedValue<unsigned int, std::string>(threadID) + ", interpreter is busy right now.");
+                    }
+                }
+
+                boost::mutex::scoped_lock queriers_lock(target->queriersMutex_);
+                target->queriers_.clear();
+            }
+        }
+        return output;
+    }
+
+    void TclThreadManager::tick(float dt)
+    {
+        {
+            this->orxonoxEvalCondition_.notify_one();
+#if (BOOST_VERSION >= 103500)
+            boost::this_thread::yield();
+#else
+            boost::thread::yield();
+#endif
+        }
+
+        {
+            boost::mutex::scoped_lock bundles_lock(this->bundlesMutex_);
+            for (std::map<unsigned int, TclInterpreterBundle*>::iterator it = this->interpreterBundles_.begin(); it != this->interpreterBundles_.end(); ++it)
+            {
+                boost::mutex::scoped_lock queue_lock((*it).second->queueMutex_);
+                if (!(*it).second->queue_.empty())
+                {
+                    std::string command = (*it).second->queue_.front();
+                    (*it).second->queue_.pop_front();
+                    {
+                        boost::mutex::scoped_lock finished_lock((*it).second->finishedMutex_);
+                        (*it).second->finished_ = false;
+                    }
+                    boost::thread(boost::bind(&tclThread, (*it).second, command));
+                }
+            }
+        }
+
+        {
+#if (BOOST_VERSION >= 103500)
+            boost::mutex::scoped_lock interpreter_lock(this->orxonoxInterpreterBundle_.interpreterMutex_);
+#else
+            boost::try_mutex::scoped_lock interpreter_lock(this->orxonoxInterpreterBundle_.interpreterMutex_);
+#endif
+            unsigned long maxtime = (unsigned long)(dt * 1000000 * TCLTHREADMANAGER_MAX_CPU_USAGE);
+            Ogre::Timer timer;
+            while (!this->queueIsEmpty())
+            {
+                CommandExecutor::execute(this->popCommandFromQueue(), false);
+                if (timer.getMicroseconds() > maxtime)
+                    break;
+            }
+        }
+    }
+
+    std::list<unsigned int> TclThreadManager::getThreadList() const
+    {
+        boost::mutex::scoped_lock bundles_lock(TclThreadManager::getInstance().bundlesMutex_);
+        std::list<unsigned int> threads;
+        for (std::map<unsigned int, TclInterpreterBundle*>::const_iterator it = this->interpreterBundles_.begin(); it != this->interpreterBundles_.end(); ++it)
+            threads.push_back((*it).first);
+        return threads;
+    }
+
+    void tclThread(TclInterpreterBundle* interpreterBundle, std::string command)
+    {
+        TclThreadManager::getInstance().debug("TclThread_execute: " + command);
+#if (BOOST_VERSION >= 103500)
+        boost::mutex::scoped_lock interpreter_lock(interpreterBundle->interpreterMutex_);
+#else
+        boost::try_mutex::scoped_lock interpreter_lock(interpreterBundle->interpreterMutex_);
+#endif
+        try
+        {
+            interpreterBundle->interpreter_->eval(command);
+        }
+        catch (Tcl::tcl_error const &e)
+        {
+            TclThreadManager::getInstance().error("Tcl (ID " + getConvertedValue<unsigned int, std::string>(interpreterBundle->id_) + ") error: " + e.what());
+        }
+        catch (std::exception const &e)
+        {
+            TclThreadManager::getInstance().error("Error while executing Tcl (ID " + getConvertedValue<unsigned int, std::string>(interpreterBundle->id_) + "): " + e.what());
+        }
+
+        boost::mutex::scoped_lock finished_lock(interpreterBundle->finishedMutex_);
+        interpreterBundle->finished_ = true;
+        interpreterBundle->finishedCondition_.notify_all();
+    }
+}
Index: code/trunk/src/core/TclThreadManager.h
===================================================================
--- code/trunk/src/core/TclThreadManager.h	(revision 1502)
+++ code/trunk/src/core/TclThreadManager.h	(revision 1502)
@@ -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:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _TclThreadManager_H__
+#define _TclThreadManager_H__
+
+#include <queue>
+#include <map>
+#include <list>
+
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/condition.hpp>
+#include <boost/thread/thread.hpp>
+
+#include "CorePrereqs.h"
+#include "Tickable.h"
+#include "cpptcl/CppTcl.h"
+
+namespace orxonox
+{
+    class boost::thread;
+
+    struct _CoreExport TclInterpreterBundle
+    {
+        unsigned int id_;
+
+        std::list<std::string> queue_;
+        boost::mutex queueMutex_;
+
+        Tcl::interpreter* interpreter_;
+        std::string interpreterName_;
+        boost::try_mutex interpreterMutex_;
+
+        std::list<unsigned int> queriers_;
+        boost::mutex queriersMutex_;
+
+        bool running_;
+        boost::mutex runningMutex_;
+
+        bool finished_;
+        boost::mutex finishedMutex_;
+        boost::condition finishedCondition_;
+    };
+
+    class _CoreExport TclThreadManager : public Tickable
+    {
+        public:
+            static TclThreadManager& getInstance();
+
+            static unsigned int create();
+            static unsigned int createID(unsigned int threadID);
+            static void destroy(unsigned int threadID);
+            static void execute(unsigned int threadID, const std::string& command);
+            static std::string query(unsigned int threadID, const std::string& command);
+            static void status();
+            static void dump(unsigned int threadID);
+            static void flush(unsigned int threadID);
+
+            static void tcl_execute(Tcl::object const &args);
+            static std::string tcl_query(int querierID, Tcl::object const &args);
+            static std::string tcl_crossquery(int querierID, int threadID, Tcl::object const &args);
+            static bool tcl_running(int threadID);
+
+            Tcl::interpreter* createNewTclInterpreter(const std::string& threadID);
+            TclInterpreterBundle* getInterpreterBundle(unsigned int threadID);
+            std::string dumpList(const std::list<unsigned int>& list);
+            void error(const std::string& error);
+            void debug(const std::string& error);
+
+            void pushCommandToQueue(const std::string& command);
+            void forceCommandToFrontOfQueue(const std::string& command);
+            std::string popCommandFromQueue();
+            bool queueIsEmpty();
+
+            void pushCommandToQueue(unsigned int threadID, const std::string& command);
+            std::string popCommandFromQueue(unsigned int threadID);
+            bool queueIsEmpty(unsigned int threadID);
+
+            bool updateQueriersList(TclInterpreterBundle* querier, TclInterpreterBundle* target);
+
+            std::string evalQuery(unsigned int querierID, const std::string& command);
+            std::string evalQuery(unsigned int querierID, unsigned int threadID, const std::string& command);
+
+            virtual void tick(float dt);
+
+            std::list<unsigned int> getThreadList() const;
+
+        private:
+            TclThreadManager();
+            TclThreadManager(const TclThreadManager& other);
+            ~TclThreadManager() {}
+
+            unsigned int threadCounter_;
+            TclInterpreterBundle orxonoxInterpreterBundle_;
+            std::map<unsigned int, TclInterpreterBundle*> interpreterBundles_;
+            boost::mutex bundlesMutex_;
+            boost::condition fullQueueCondition_;
+            boost::condition orxonoxEvalCondition_;
+#if (BOOST_VERSION >= 103500)
+            boost::thread::id threadID_;
+#else
+            boost::thread threadID_;
+#endif
+    };
+
+    _CoreExport void tclThread(TclInterpreterBundle* interpreterBundle, std::string command);
+}
+
+#endif /* _TclThreadManager_H__ */
Index: code/trunk/src/core/XMLPort.h
===================================================================
--- code/trunk/src/core/XMLPort.h	(revision 1407)
+++ code/trunk/src/core/XMLPort.h	(revision 1502)
@@ -78,17 +78,4 @@
 namespace orxonox
 {
-
-#ifndef _XMLPort_Mode__
-#define _XMLPort_Mode__
-    namespace XMLPort
-    {
-        enum Mode
-        {
-            LoadObject,
-            SaveObject
-        };
-    }
-#endif
-
     // ###############################
     // ###  XMLPortParamContainer  ###
@@ -166,5 +153,5 @@
                         }
                     }
-                    catch(ticpp::Exception& ex)
+                    catch (ticpp::Exception& ex)
                     {
                         COUT(1) << std::endl;
@@ -344,5 +331,5 @@
                         }
                     }
-                    catch(ticpp::Exception& ex)
+                    catch (ticpp::Exception& ex)
                     {
                         COUT(1) << std::endl;
Index: code/trunk/src/cpptcl/CppTcl.cc
===================================================================
--- code/trunk/src/cpptcl/CppTcl.cc	(revision 1407)
+++ code/trunk/src/cpptcl/CppTcl.cc	(revision 1502)
@@ -953,4 +953,8 @@
 
      {
+          // TODO: why could this probably be necessary? map::find of empty map
+          // shouldn't be a problem.
+          if (callbacks.size() == 0)
+            return;
           callback_map::iterator it = callbacks.find(interp);
           if (it == callbacks.end())
Index: code/trunk/src/network/CMakeLists.txt
===================================================================
--- code/trunk/src/network/CMakeLists.txt	(revision 1407)
+++ code/trunk/src/network/CMakeLists.txt	(revision 1502)
Index: code/trunk/src/network/Client.cc
===================================================================
--- code/trunk/src/network/Client.cc	(revision 1407)
+++ code/trunk/src/network/Client.cc	(revision 1502)
@@ -85,4 +85,5 @@
     isConnected=false;
     isSynched_=false;
+    gameStateFailure_=false;
   }
 
@@ -95,4 +96,5 @@
     isConnected=false;
     isSynched_=false;
+    gameStateFailure_=false;
   }
 
@@ -105,4 +107,5 @@
     isConnected=false;
     isSynched_=false;
+    gameStateFailure_=false;
   }
 
@@ -120,9 +123,9 @@
     isConnected=client_connection.createConnection();
     if(isConnected){
-      COUT(3) << "sending connectrequest" << std::endl;
-      if(!client_connection.addPacket(pck_gen.generateConnectRequest()) || !client_connection.sendPackets())
-        COUT(1) << "could not create connection" << std::endl;
+//       COUT(3) << "sending connectrequest" << std::endl;
+//       if(!client_connection.addPacket(pck_gen.generateConnectRequest()) || !client_connection.sendPackets())
+//         COUT(1) << "could not send connection request !!!!!!!!!" << std::endl;
     }else
-      COUT(1) << "could not create connection" << std::endl;
+      COUT(1) << "could not create connection laber" << std::endl;
     return isConnected;
   }
@@ -137,34 +140,7 @@
   }
 
-  /**
-  * submits a MouseAction to the server
-  * @param x x Coordinate
-  * @param y y Coordinate
-  * @return true/false
-  */
-  bool Client::sendMouse(double x, double y){
-    // generate packet and add it to the queue
-    if(!isConnected)
-      return false;
-    if(!client_connection.addPacket(pck_gen.mousem(x, y)))
-      return false;
-    // send packets
-    return client_connection.sendPackets();
-  }
-
-  /**
-  * submits a Keystrike to the server
-  * @param key_code code to submit
-  * @return true/false
-  */
-  bool Client::sendKeyboard(char key_code){
-    // generate packet and add it to queue
-    if(!isConnected)
-      return false;
-    if(!client_connection.addPacket(pck_gen.keystrike(key_code)))
-      return false;
-    // send packets
-    return client_connection.sendPackets();
-  }
+  
+
+  
 
   /**
@@ -177,50 +153,8 @@
     if(!isConnected)
       return false;
-    if(client_connection.addPacket(pck_gen.chatMessage( message.c_str() )))
-      return client_connection.sendPackets();
+    return client_connection.addPacket(pck_gen.chatMessage( message.c_str() ));
+      //return client_connection.sendPackets();
     // send packets
     return false;
-  }
-
-  /**
-  * Adds a MouseAction to the PacketQueue
-  * @param x x Coordinate
-  * @param y y Coordinate
-  * @return true/false
-  */
-  bool Client::addMouse(double x, double y){
-    // generate packet and add it to the queue
-    if(client_connection.addPacket(pck_gen.mousem(x, y)))
-      return true;
-    else
-      return false;
-  }
-
-  /**
-  * Adds a Keystrike to the PacketQueue
-  * @param key_code
-  * @return true/false
-  */
-  bool Client::addKeyboard(char key_code){
-    // generate packet and add it to queue
-    if(client_connection.addPacket(pck_gen.keystrike(key_code)))
-      return true;
-    else
-      return false;
-  }
-
-  /**
-  * Sends out all the packets queued by addXXX
-  */
-  bool Client::sendPackets(){
-    if(!isConnected)
-      return false;
-    ENetEvent event;
-    // send packets
-    client_connection.sendPackets(&event);
-    if(event.type==ENET_EVENT_TYPE_NONE)
-      return true;
-    else
-      return false;
   }
 
@@ -243,28 +177,38 @@
       }
     }
-    ENetPacket *packet;
+    ENetEvent *event;
     // stop if the packet queue is empty
     while(!(client_connection.queueEmpty())){
-      packet = client_connection.getPacket();
-      COUT(5) << "tick packet size " << packet->dataLength << std::endl;
-      elaborate(packet, 0); // ================= i guess we got to change this .... (client_ID is always same = server)
-    }
-    if(!client_connection.sendPackets())
-      COUT(3) << "Problem sending packets to server" << std::endl;
-    return;
-  }
-
-  void Client::processGamestate( GameStateCompressed *data, int clientID){
-    int id = data->id;
-    COUT(5) << "received gamestate id: " << data->id << std::endl;
-    if(gamestate.pushGameState(data)){
+      event = client_connection.getEvent();
+      COUT(5) << "tick packet size " << event->packet->dataLength << std::endl;
+      elaborate(event->packet, 0); // ================= i guess we got to change this .... (client_ID is always same = server)
+    }
+    int gameStateID = gamestate.processGameState();
+    if(gameStateID==GAMESTATEID_INITIAL)
+      if(gameStateFailure_){
+        if(!client_connection.addPacket(pck_gen.acknowledgement(GAMESTATEID_INITIAL)))
+          COUT(3) << "could not (negatively) ack gamestate" << std::endl;
+        else 
+          COUT(4) << "negatively acked a gamestate" << std::endl;
+        }
+      else
+        gameStateFailure_=true;
+    else if(gameStateID!=0){
+      // ack gamestate and set synched
       if(!isSynched_)
         isSynched_=true;
-      if(!client_connection.addPacket(pck_gen.acknowledgement(id)))
-        return;
-        // we do this at the end of a tick
-      if(!client_connection.sendPackets())
-        COUT(2) << "Could not send acknowledgment" << std::endl;
-    }
+      gameStateFailure_=false;
+      if(!client_connection.addPacket(pck_gen.acknowledgement(gameStateID)))
+        COUT(3) << "could not ack gamestate" << std::endl;
+    }// otherwise we had no gamestate to load
+    gamestate.cleanup();
+    /*if(!client_connection.sendPackets())
+      COUT(3) << "Problem sending packets to server" << std::endl;*/
+    return;
+  }
+
+  void Client::processGamestate( GameStateCompressed *data, int clientID){
+    COUT(5) << "received gamestate id: " << data->id << std::endl;
+    gamestate.addGameState(data);
   }
 
@@ -275,4 +219,5 @@
       id->setNetworkID(clid->clid);
     COUT(4) << "Client: received and set network id: " << clid->clid << "; classname: " << clid->message << std::endl;
+    COUT(4) << "id(classid)->getName " << ID((unsigned int)clid->clid)->getName() << std::endl;
     delete clid;
     return;
Index: code/trunk/src/network/Client.h
===================================================================
--- code/trunk/src/network/Client.h	(revision 1407)
+++ code/trunk/src/network/Client.h	(revision 1502)
@@ -75,12 +75,5 @@
     bool closeConnection();
 
-    bool sendMouse(double x, double y);
-    bool sendKeyboard(char key_code);
     bool sendChat( std::string message );
-
-    bool addMouse(double x, double y);
-    bool addKeyboard(char key_code);
-
-    bool sendPackets();
     
     int getShipID(){return shipID_;}
@@ -110,4 +103,5 @@
     int clientID_;     // this is the id the server gave to us
     int shipID_;
+    bool gameStateFailure_;
   };
 
Index: code/trunk/src/network/ClientConnection.cc
===================================================================
--- code/trunk/src/network/ClientConnection.cc	(revision 1407)
+++ code/trunk/src/network/ClientConnection.cc	(revision 1502)
@@ -50,4 +50,6 @@
 {
   //static boost::thread_group network_threads;
+
+  boost::recursive_mutex ClientConnection::enet_mutex_;
 
   ClientConnection::ClientConnection(int port, std::string address) {
@@ -75,5 +77,5 @@
 
 
-  ENetPacket *ClientConnection::getPacket(ENetAddress &address) {
+  /*ENetPacket *ClientConnection::getPacket(ENetAddress &address) {
     if(!buffer.isEmpty()) {
       //std::cout << "###BUFFER IS NOT EMPTY###" << std::endl;
@@ -88,4 +90,11 @@
     ENetAddress address; //sems that address is not needed
     return getPacket(address);
+  }*/
+  
+  ENetEvent *ClientConnection::getEvent(){
+    if(!buffer.isEmpty())
+      return buffer.pop();
+    else
+      return NULL;
   }
 
@@ -98,5 +107,5 @@
     //network_threads.create_thread(boost::bind(boost::mem_fn(&ClientConnection::receiverThread), this));
     // wait 10 seconds for the connection to be established
-    return waitEstablished(10000);
+    return waitEstablished(3000);
   }
 
@@ -117,4 +126,5 @@
       return false;
     }
+    boost::recursive_mutex::scoped_lock lock(enet_mutex_);
     if(enet_peer_send(server, 0, packet)<0)
       return false;
@@ -123,52 +133,57 @@
   }
 
-  bool ClientConnection::sendPackets(ENetEvent *event) {
+  bool ClientConnection::sendPackets() {
     if(server==NULL)
       return false;
-    if(enet_host_service(client, event, NETWORK_SEND_WAIT)>=0){
-      return true;}
-    else
-      return false;
-  }
-
-  bool ClientConnection::sendPackets() {
-    ENetEvent event;
-    if(server==NULL)
-      return false;
-    if(enet_host_service(client, &event, NETWORK_SEND_WAIT)>=0){
-      return true;}
-    else
-      return false;
+    boost::recursive_mutex::scoped_lock lock(enet_mutex_);
+    enet_host_flush(client);
+    lock.unlock();
+    return true;
   }
 
   void ClientConnection::receiverThread() {
     // what about some error-handling here ?
-    enet_initialize();
     atexit(enet_deinitialize);
-    ENetEvent event;
-    client = enet_host_create(NULL, NETWORK_CLIENT_MAX_CONNECTIONS, 0, 0);
-    if(client==NULL)
+    ENetEvent *event;
+    {
+      boost::recursive_mutex::scoped_lock lock(enet_mutex_);
+      enet_initialize();
+      client = enet_host_create(NULL, NETWORK_CLIENT_MAX_CONNECTIONS, 0, 0);
+      lock.unlock();
+    }
+    if(client==NULL) {
+      COUT(2) << "ClientConnection: could not create client host" << std::endl;
       // add some error handling here ==========================
       quit=true;
+    }
     //connect to the server
     if(!establishConnection()){
+      COUT(2) << "clientConn: receiver thread: could not establishConnection" << std::endl;
       quit=true;
       return;
     }
+    event = new ENetEvent;
     //main loop
     while(!quit){
       //std::cout << "connection loop" << std::endl;
-      if(enet_host_service(client, &event, NETWORK_CLIENT_TIMEOUT)<0){
-        // we should never reach this point
-        quit=true;
-        // add some error handling here ========================
+      {
+        boost::recursive_mutex::scoped_lock lock(enet_mutex_);
+        if(enet_host_service(client, event, NETWORK_CLIENT_TIMEOUT)<0){
+          // we should never reach this point
+          quit=true;
+          continue;
+          // add some error handling here ========================
+        }
+        lock.unlock();
       }
-      switch(event.type){
+      switch(event->type){
         // log handling ================
       case ENET_EVENT_TYPE_CONNECT:
+        break;
       case ENET_EVENT_TYPE_RECEIVE:
         COUT(5) << "Cl.Con: receiver-Thread while loop: got new packet" << std::endl;
-        if ( !processData(&event) ) COUT(2) << "Current packet was not pushed to packetBuffer -> ev ongoing SegFault" << std::endl;
+        if ( !processData(event) ) COUT(2) << "Current packet was not pushed to packetBuffer -> ev ongoing SegFault" << std::endl;
         COUT(5) << "Cl.Con: processed Data in receiver-thread while loop" << std::endl;
+        event = new ENetEvent;
         break;
       case ENET_EVENT_TYPE_DISCONNECT:
@@ -178,7 +193,8 @@
         break;
       case ENET_EVENT_TYPE_NONE:
-        continue;
+        //receiverThread_->yield();
+        usleep(1000);
+        break;
       }
-      //receiverThread_->yield();
     }
     // now disconnect
@@ -186,4 +202,5 @@
     if(!disconnectConnection())
       // if disconnecting failed destroy conn.
+      boost::recursive_mutex::scoped_lock lock(enet_mutex_);
       enet_peer_reset(server);
     return;
@@ -192,4 +209,5 @@
   bool ClientConnection::disconnectConnection() {
     ENetEvent event;
+    boost::recursive_mutex::scoped_lock lock(enet_mutex_);
     enet_peer_disconnect(server, 0);
     while(enet_host_service(client, &event, NETWORK_CLIENT_TIMEOUT) > 0){
@@ -212,15 +230,20 @@
     ENetEvent event;
     // connect to peer (server is type ENetPeer*)
+    boost::recursive_mutex::scoped_lock lock(enet_mutex_);
     server = enet_host_connect(client, &serverAddress, NETWORK_CLIENT_CHANNELS);
-    if(server==NULL)
+    if(server==NULL) {
+      COUT(2) << "ClientConnection: server == NULL" << std::endl;
       // error handling
       return false;
+    }
     // handshake
-    if(enet_host_service(client, &event, NETWORK_CLIENT_TIMEOUT)>0 && event.type == ENET_EVENT_TYPE_CONNECT){
+    if(enet_host_service(client, &event, NETWORK_CLIENT_TIMEOUT)>=0 && event.type == ENET_EVENT_TYPE_CONNECT){
       established=true;
       return true;
     }
-    else
-      return false;
+    else {
+      COUT(2) << "ClientConnection: enet_host_service < 0 or event.type != ENET_EVENT_TYPE_CONNECT # EVENT:" << event.type << std::endl;
+      return false;
+    }
   }
 
Index: code/trunk/src/network/ClientConnection.h
===================================================================
--- code/trunk/src/network/ClientConnection.h	(revision 1407)
+++ code/trunk/src/network/ClientConnection.h	(revision 1502)
@@ -54,6 +54,5 @@
 #define NETWORK_PORT 55556
 #define NETWORK_CLIENT_MAX_CONNECTIONS 5
-#define NETWORK_CLIENT_TIMEOUT 100
-#define NETWORK_SEND_WAIT 5
+#define NETWORK_CLIENT_TIMEOUT 1
 #define NETWORK_CLIENT_CHANNELS 2
 
@@ -63,6 +62,7 @@
     ClientConnection(int port, std::string address);
     ClientConnection(int port, const char* address);
-    ENetPacket *getPacket(ENetAddress &address); // thread1
-    ENetPacket *getPacket(); // thread1
+    //ENetPacket *getPacket(ENetAddress &address); // thread1
+    //ENetPacket *getPacket(); // thread1
+    ENetEvent *getEvent();
     // check wheter the packet queue is empty
     bool queueEmpty();
@@ -75,5 +75,5 @@
     bool sendPackets();
     // send out all queued packets and save result in event
-    bool sendPackets(ENetEvent *event);
+    //bool sendPackets(ENetEvent *event);
     bool waitEstablished(int milisec);
     bool isConnected(){return established;}
@@ -95,4 +95,6 @@
     ENetPeer *server;
     boost::thread *receiverThread_;
+    
+    static boost::recursive_mutex enet_mutex_;
   };
 
Index: code/trunk/src/network/ClientInformation.cc
===================================================================
--- code/trunk/src/network/ClientInformation.cc	(revision 1407)
+++ code/trunk/src/network/ClientInformation.cc	(revision 1502)
@@ -45,5 +45,4 @@
 namespace network
 {
-  boost::recursive_mutex ClientInformation::mutex_;
   
   ClientInformation::ClientInformation() {
@@ -84,13 +83,11 @@
 
   ClientInformation::~ClientInformation() {
-    boost::recursive_mutex::scoped_lock lock(mutex_);
-    if(preve!=0)
-      preve->setNext(this->nexte);
-    if(nexte!=0)
-      nexte->setPrev(this->preve);
+    if(prev()!=0)
+      prev()->setNext(this->next());
+    if(next()!=0)
+      next()->setPrev(this->prev());
   }
 
   ClientInformation *ClientInformation::next() {
-    boost::recursive_mutex::scoped_lock lock(mutex_);
     if(this!=0)
       return this->nexte;
@@ -99,5 +96,4 @@
   }
   ClientInformation *ClientInformation::prev() {
-    boost::recursive_mutex::scoped_lock lock(mutex_);
     if(this!=0)
       return this->preve;
@@ -107,5 +103,4 @@
 
   bool ClientInformation::setPrev(ClientInformation *prev) {
-    boost::recursive_mutex::scoped_lock lock(mutex_);
     if(!head_)
       this->preve = prev;
@@ -116,5 +111,4 @@
 
   bool ClientInformation::setNext(ClientInformation *next) {
-    boost::recursive_mutex::scoped_lock lock(mutex_);
     this->nexte = next;
     return true;
@@ -122,7 +116,6 @@
 
   ClientInformation *ClientInformation::insertAfter(ClientInformation *ins) {
-    boost::recursive_mutex::scoped_lock lock(mutex_);
-    this->nexte->setPrev(ins);
-    ins->setNext(this->nexte);
+    this->next()->setPrev(ins);
+    ins->setNext(this->next());
     ins->setPrev(this);
     this->nexte = ins;
@@ -131,9 +124,8 @@
 
   ClientInformation *ClientInformation::insertBefore(ClientInformation *ins){
-    boost::recursive_mutex::scoped_lock lock(mutex_);
     if(!this)
       return NULL;
     this->prev()->setNext(ins);
-    ins->setPrev(this->preve);
+    ins->setPrev(this->prev());
     this->preve=ins;
     ins->setNext(this);
@@ -142,10 +134,10 @@
 
   void ClientInformation::setID(int clientID){
-    boost::recursive_mutex::scoped_lock lock(mutex_);
+    if(!this)
+      return;
     clientID_ = clientID;
   }
 
   bool ClientInformation::setPeer(ENetPeer *peer){
-    boost::recursive_mutex::scoped_lock lock(mutex_);
     if(!this)
       return false;
@@ -154,6 +146,5 @@
   }
 
-  bool ClientInformation::setGamestateID(int id){
-    boost::recursive_mutex::scoped_lock lock(mutex_);
+  bool ClientInformation::setGameStateID(int id){
     if(!this)
       return false;
@@ -163,5 +154,4 @@
   
   bool ClientInformation::setPartialGamestateID(int id){
-    boost::recursive_mutex::scoped_lock lock(mutex_);
     if(!this)
       return false;
@@ -171,5 +161,4 @@
 
   int ClientInformation::getID() {
-    boost::recursive_mutex::scoped_lock lock(mutex_);
     if(!this)
       return CLIENTID_UNKNOWN;
@@ -179,5 +168,4 @@
 
   ENetPeer *ClientInformation::getPeer() {
-    boost::recursive_mutex::scoped_lock lock(mutex_);
     if(this)
       return peer_;
@@ -187,28 +175,22 @@
   
   bool ClientInformation::getHead(){
-    boost::recursive_mutex::scoped_lock lock(mutex_);
     return head_;
   }
   
   void ClientInformation::setHead(bool h){
-    boost::recursive_mutex::scoped_lock lock(mutex_);
     head_=h;
   }
   
   int ClientInformation::getFailures(){
-    boost::recursive_mutex::scoped_lock lock(mutex_);
     return failures_;
   }
   void ClientInformation::addFailure(){
-    boost::recursive_mutex::scoped_lock lock(mutex_);
     failures_++;
   }
   void ClientInformation::resetFailures(){
-    boost::recursive_mutex::scoped_lock lock(mutex_);
     failures_=0;
   }
 
   int ClientInformation::getGamestateID() {
-    boost::recursive_mutex::scoped_lock lock(mutex_);
     if(this)
       return gamestateID_;
@@ -218,5 +200,4 @@
   
   int ClientInformation::getPartialGamestateID() {
-    boost::recursive_mutex::scoped_lock lock(mutex_);
     if(this)
       return partialGamestateID_;
@@ -226,5 +207,4 @@
 
   ClientInformation *ClientInformation::insertBack(ClientInformation *ins) {
-    boost::recursive_mutex::scoped_lock lock(mutex_);
     if(!this)
       return NULL;
@@ -239,5 +219,4 @@
 
   bool ClientInformation::removeClient(int clientID) {
-    boost::recursive_mutex::scoped_lock lock(mutex_);
     if(!this || clientID==CLIENTID_UNKNOWN)
       return false;
@@ -252,5 +231,4 @@
 
   bool ClientInformation::removeClient(ENetPeer *peer) {
-    boost::recursive_mutex::scoped_lock lock(mutex_);
     if(!this || !peer)
       return false;
@@ -275,5 +253,4 @@
   */
   ClientInformation *ClientInformation::findClient(int clientID, bool look_backwards) {
-    boost::recursive_mutex::scoped_lock lock(mutex_);
     ClientInformation *temp = this;
     if (temp->head_)
@@ -293,5 +270,4 @@
   */
   ClientInformation *ClientInformation::findClient(ENetAddress *address, bool look_backwards) {
-    boost::recursive_mutex::scoped_lock lock(mutex_);
     ClientInformation *temp = this;
     while(temp!=0){
@@ -309,5 +285,4 @@
 
   bool ClientInformation::setSynched(bool s) {
-    boost::recursive_mutex::scoped_lock lock(mutex_);
     if(!this)
       return false;
@@ -317,5 +292,4 @@
 
   bool ClientInformation::getSynched() {
-    boost::recursive_mutex::scoped_lock lock(mutex_);
     if(this)
       return synched_;
Index: code/trunk/src/network/ClientInformation.h
===================================================================
--- code/trunk/src/network/ClientInformation.h	(revision 1407)
+++ code/trunk/src/network/ClientInformation.h	(revision 1502)
@@ -49,4 +49,6 @@
 #define CLIENTID_UNKNOWN -2
 
+// WATCH OUT: THE CLIENTINFORMATION LIST IS NOT THREADSAFE ANYMORE
+
 namespace network
 {
@@ -69,5 +71,5 @@
     void setID(int clientID);
     bool setPeer(ENetPeer *peer);
-    bool setGamestateID(int id);
+    bool setGameStateID(int id);
     bool setPartialGamestateID(int id);
     inline void setShipID(int id){ShipID_=id;}
@@ -114,5 +116,4 @@
     bool head_;
     unsigned short failures_;
-    static boost::recursive_mutex mutex_;
     
   };
Index: code/trunk/src/network/ConnectionManager.cc
===================================================================
--- code/trunk/src/network/ConnectionManager.cc	(revision 1407)
+++ code/trunk/src/network/ConnectionManager.cc	(revision 1502)
@@ -44,6 +44,7 @@
 #include "core/CoreIncludes.h"
 #include "core/BaseObject.h"
+#include "objects/SpaceShip.h"
 #include "util/Math.h"
-#include "objects/SpaceShip.h"
+#include "util/Sleep.h"
 #include "ClientInformation.h"
 #include "ConnectionManager.h"
@@ -65,4 +66,5 @@
   
   ConnectionManager::ConnectionManager():receiverThread_(0){}
+  boost::recursive_mutex ConnectionManager::enet_mutex_;
   
   ConnectionManager::ConnectionManager(ClientInformation *head) : receiverThread_(0) {
@@ -72,4 +74,11 @@
     head_ = head;
   }
+  
+  ConnectionManager::ConnectionManager(ClientInformation *head, int port){
+    quit=false;
+    bindAddress.host = ENET_HOST_ANY;
+    bindAddress.port = port;
+    head_ = head;
+  }
 
   ConnectionManager::ConnectionManager(int port, std::string address, ClientInformation *head) :receiverThread_(0) {
@@ -87,15 +96,15 @@
   }
 
-  ENetPacket *ConnectionManager::getPacket(ENetAddress &address) {
+  /*ENetPacket *ConnectionManager::getPacket(ENetAddress &address) {
     if(!buffer.isEmpty())
       return buffer.pop(address);
     else
       return NULL;
-  }
+  }*/
 /**
 This function only pops the first element in PacketBuffer (first in first out)
 used by processQueue in Server.cc
 */
-  ENetPacket *ConnectionManager::getPacket(int &clientID) {
+  /*ENetPacket *ConnectionManager::getPacket(int &clientID) {
     ENetAddress address;
     ENetPacket *packet=getPacket(address);
@@ -105,4 +114,11 @@
     clientID=temp->getID();
     return packet;
+  }*/
+  
+  ENetEvent *ConnectionManager::getEvent(){
+    if(!buffer.isEmpty())
+      return buffer.pop();
+    else
+      return NULL;
   }
 
@@ -129,4 +145,5 @@
     if(!temp)
       return false;
+    boost::recursive_mutex::scoped_lock lock(enet_mutex_);
     if(enet_peer_send(peer, (enet_uint8)temp->getID() , packet)!=0)
       return false;
@@ -136,12 +153,18 @@
   bool ConnectionManager::addPacket(ENetPacket *packet, int clientID) {
     ClientInformation *temp = head_->findClient(clientID);
-    if(!temp)
-      return false;
-    if(enet_peer_send(temp->getPeer(), (enet_uint8)clientID, packet)!=0)
-      return false;
+    if(!temp){
+      COUT(3) << "C.Man: addPacket findClient failed" << std::endl;
+      return false;
+    }
+    boost::recursive_mutex::scoped_lock lock(enet_mutex_);
+    if(enet_peer_send(temp->getPeer(), 0, packet)!=0){
+      COUT(3) << "C.Man: addPacket enet_peer_send failed" << std::endl;
+      return false;
+    }
     return true;
   }
 
   bool ConnectionManager::addPacketAll(ENetPacket *packet) {
+    boost::recursive_mutex::scoped_lock lock(enet_mutex_);
     for(ClientInformation *i=head_->next(); i!=0; i=i->next()){
       if(enet_peer_send(i->getPeer(), (enet_uint8)i->getID(), packet)!=0)
@@ -151,29 +174,24 @@
   }
 
-  bool ConnectionManager::sendPackets(ENetEvent *event) {
+  // we actually dont need that function, because host_service does that for us
+  bool ConnectionManager::sendPackets() {
     if(server==NULL)
       return false;
-    if(enet_host_service(server, event, NETWORK_SEND_WAIT)>=0)
-      return true;
-    else
-      return false;
-  }
-
-  bool ConnectionManager::sendPackets() {
-    ENetEvent event;
-    if(server==NULL)
-      return false;
-    if(enet_host_service(server, &event, NETWORK_SEND_WAIT)>=0)
-      return true;
-    else
-      return false;
+    boost::recursive_mutex::scoped_lock lock(enet_mutex_);
+    enet_host_flush(server);
+    lock.unlock();
+    return true;
   }
 
   void ConnectionManager::receiverThread() {
     // what about some error-handling here ?
-    enet_initialize();
+    ENetEvent *event;
     atexit(enet_deinitialize);
-    ENetEvent *event = new ENetEvent;
-    server = enet_host_create(&bindAddress, NETWORK_MAX_CONNECTIONS, 0, 0);
+    { //scope of the mutex
+      boost::recursive_mutex::scoped_lock lock(enet_mutex_);
+      enet_initialize();
+      server = enet_host_create(&bindAddress, NETWORK_MAX_CONNECTIONS, 0, 0);
+      lock.unlock();
+    }
     if(server==NULL){
       // add some error handling here ==========================
@@ -182,39 +200,53 @@
     }
 
+    event = new ENetEvent;
     while(!quit){
-      if(enet_host_service(server, event, NETWORK_WAIT_TIMEOUT)<0){
-        // we should never reach this point
-        quit=true;
-        // add some error handling here ========================
+      { //mutex scope
+        boost::recursive_mutex::scoped_lock lock(enet_mutex_);
+        if(enet_host_service(server, event, NETWORK_WAIT_TIMEOUT)<0){
+          // we should never reach this point
+          quit=true;
+          continue;
+          // add some error handling here ========================
+        }
+        lock.unlock();
       }
       switch(event->type){
         // log handling ================
         case ENET_EVENT_TYPE_CONNECT:
-          addClient(event);
+          COUT(3) << "adding event_type_connect to queue" << std::endl;
+        case ENET_EVENT_TYPE_DISCONNECT:
+          //addClient(event);
           //this is a workaround to ensure thread safety
-          COUT(5) << "Con.Man: connection event has occured" << std::endl;
-          break;
+          //COUT(5) << "Con.Man: connection event has occured" << std::endl;
+          //break;
         case ENET_EVENT_TYPE_RECEIVE:
           //std::cout << "received data" << std::endl;
           COUT(5) << "Con.Man: receive event has occured" << std::endl;
           // only add, if client has connected yet and not been disconnected
-          if(head_->findClient(&event->peer->address))
+          //if(head_->findClient(&event->peer->address))
             processData(event);
-          else
-            COUT(3) << "received a packet from a client we don't know" << std::endl;
+            event = new ENetEvent;
+//           else
+//             COUT(3) << "received a packet from a client we don't know" << std::endl;
           break;
-        case ENET_EVENT_TYPE_DISCONNECT:
-          clientDisconnect(event->peer);
+        //case ENET_EVENT_TYPE_DISCONNECT:
+          //clientDisconnect(event->peer);
+          //break;
+        case ENET_EVENT_TYPE_NONE:
+          //receiverThread_->yield();
+          usleep(1000);
           break;
-        case ENET_EVENT_TYPE_NONE:
-          receiverThread_->yield();
-          break;
       }
 //       usleep(100);
-      receiverThread_->yield(); //TODO: find apropriate
+      //receiverThread_->yield(); //TODO: find apropriate
     }
     disconnectClients();
     // if we're finishied, destroy server
-    enet_host_destroy(server);
+    {
+      boost::recursive_mutex::scoped_lock lock(enet_mutex_);
+      enet_host_destroy(server);
+      lock.unlock();
+    }
   }
   
@@ -226,11 +258,15 @@
     ClientInformation *temp = head_->next();
     while(temp!=0){
-      enet_peer_disconnect(temp->getPeer(), 0);
+      {
+        boost::recursive_mutex::scoped_lock lock(enet_mutex_);
+        enet_peer_disconnect(temp->getPeer(), 0);
+        lock.unlock();
+      }
       temp = temp->next();
     }
     //bugfix: might be the reason why server crashes when clients disconnects
-    //temp = temp->next();
     temp = head_->next();
-    while( temp!=0 && enet_host_service(server, &event, NETWORK_WAIT_TIMEOUT) > 0){
+    boost::recursive_mutex::scoped_lock lock(enet_mutex_);
+    while( temp!=0 && enet_host_service(server, &event, NETWORK_WAIT_TIMEOUT) >= 0){
       switch (event.type)
       {
@@ -258,29 +294,5 @@
   }
 
-  bool ConnectionManager::clientDisconnect(ENetPeer *peer) {
-    COUT(4) << "removing client from list" << std::endl;
-    return removeClient(head_->findClient(&(peer->address))->getID());
-  }
-/**
-This function adds a client that connects to the clientlist of the server
-NOTE: if you change this, don't forget to change the test function
-addClientTest in diffTest.cc since addClient is not good for testing because of syncClassid
-*/
-  bool ConnectionManager::addClient(ENetEvent *event) {
-    ClientInformation *temp = head_->insertBack(new ClientInformation);
-    if(!temp){
-      COUT(2) << "Conn.Man. could not add client" << std::endl;
-      return false;
-    }
-    if(temp->prev()->getHead()) { //not good if you use anything else than insertBack
-      temp->prev()->setID(0); //bugfix: not necessary but usefull
-      temp->setID(1);
-    }
-    else
-      temp->setID(temp->prev()->getID()+1);
-    temp->setPeer(event->peer);
-    COUT(3) << "Con.Man: added client id: " << temp->getID() << std::endl;
-    return true;
-  }
+
 
   int ConnectionManager::getClientID(ENetPeer peer) {
@@ -316,73 +328,9 @@
       ++it;
     }
-    sendPackets();
+    //sendPackets();
     COUT(4) << "syncClassid:\tall synchClassID packets have been sent" << std::endl;
   }
 
-  bool ConnectionManager::createClient(int clientID){
-    ClientInformation *temp = head_->findClient(clientID);
-    if(!temp){
-      COUT(2) << "Conn.Man. could not create client with id: " << clientID << std::endl;
-      return false;
-    }
-    COUT(4) << "Con.Man: creating client id: " << temp->getID() << std::endl;
-    syncClassid(temp->getID());
-    COUT(4) << "creating spaceship for clientid: " << temp->getID() << std::endl;
-    // TODO: this is only a hack, untill we have a possibility to define default player-join actions
-    if(!createShip(temp))
-      COUT(2) << "Con.Man. could not create ship for clientid: " << clientID << std::endl;
-    else
-      COUT(3) << "created spaceship" << std::endl;
-    temp->setSynched(true);
-    COUT(3) << "sending welcome" << std::endl;
-    sendWelcome(temp->getID(), temp->getShipID(), true);
-    return true;
-  }
-  
-  bool ConnectionManager::removeClient(int clientID){
-    orxonox::Iterator<orxonox::SpaceShip> it = orxonox::ObjectList<orxonox::SpaceShip>::start();
-    ClientInformation *client = head_->findClient(clientID);
-    if(!client)
-      return false;
-    while(it){
-      if(it->objectID!=client->getShipID()){
-        ++it;
-        continue;
-      }
-      orxonox::Iterator<orxonox::SpaceShip> temp=it;
-      ++it;
-      delete  *temp;
-      return head_->removeClient(clientID);
-    }
-    return false;
-  }
-  
-  bool ConnectionManager::createShip(ClientInformation *client){
-    if(!client)
-      return false;
-    orxonox::Identifier* id = ID("SpaceShip");
-    if(!id){
-      COUT(4) << "We could not create the SpaceShip for client: " << client->getID() << std::endl;
-      return false;
-    }
-    orxonox::SpaceShip *no = dynamic_cast<orxonox::SpaceShip *>(id->fabricate());
-    no->setPosition(orxonox::Vector3(0,80,0));
-    no->setScale(10);
-    no->setYawPitchRoll(orxonox::Degree(-90),orxonox::Degree(-90),orxonox::Degree(0));
-    no->setMesh("assff.mesh");
-    no->setMaxSpeed(500);
-    no->setMaxSideAndBackSpeed(50);
-    no->setMaxRotation(1.0);
-    no->setTransAcc(200);
-    no->setRotAcc(3.0);
-    no->setTransDamp(75);
-    no->setRotDamp(1.0);
-    no->setCamera("cam_"+client->getID());
-    no->classID = id->getNetworkID();
-    no->create();
-    
-    client->setShipID(no->objectID);
-    return true;
-  }
+  
   
   bool ConnectionManager::removeShip(ClientInformation *client){
@@ -399,5 +347,5 @@
   bool ConnectionManager::sendWelcome(int clientID, int shipID, bool allowed){
     if(addPacket(packet_gen.generateWelcome(clientID, shipID, allowed),clientID)){
-      sendPackets();
+      //sendPackets();
       return true;
     }else
@@ -406,5 +354,9 @@
   
   void ConnectionManager::disconnectClient(ClientInformation *client){
-    enet_peer_disconnect(client->getPeer(), 0);
+    {
+      boost::recursive_mutex::scoped_lock lock(enet_mutex_);
+      enet_peer_disconnect(client->getPeer(), 0);
+      lock.unlock();
+    }
     removeShip(client);
   }
@@ -418,36 +370,4 @@
   
   
-//   int ConnectionManager::getNumberOfClients() {
-//     
-//     return clientsShip.size();
-//   }
-  
-  /*void ConnectionManager::addClientsObjectID( int clientID, int objectID ) {
-  COUT(4) << "ship of client: " << clientID << ": " << objectID << " mapped" << std::endl;
-  clientsShip.insert( std::make_pair( clientID, objectID ) );
+
 }
-
-  int ConnectionManager::getClientsShipID( int clientID ) {
-  return clientsShip[clientID];
-}
-
-  int ConnectionManager::getObjectsClientID( int objectID ) {
-  std::map<int, int>::iterator iter;
-  for( iter = clientsShip.begin(); iter != clientsShip.end(); iter++ ) {
-  if( iter->second == objectID ) return iter->first;
-}
-  return -99;
-}
-
-  void ConnectionManager::deleteClientIDReg( int clientID ) {
-  clientsShip.erase( clientID );
-}
-
-  void ConnectionManager::deleteObjectIDReg( int objectID ) {
-  std::map<int, int>::iterator iter = clientsShip.begin();
-  for( iter = clientsShip.begin(); iter != clientsShip.end(); iter++ ) {
-  if( iter->second == objectID ) break;
-}
-  clientsShip.erase( iter->first );
-}*/
-}
Index: code/trunk/src/network/ConnectionManager.h
===================================================================
--- code/trunk/src/network/ConnectionManager.h	(revision 1407)
+++ code/trunk/src/network/ConnectionManager.h	(revision 1502)
@@ -48,4 +48,5 @@
 #include <enet/enet.h>
 #include <boost/thread/thread.hpp>
+#include <boost/thread/recursive_mutex.hpp>
 
 #include "PacketBuffer.h"
@@ -61,6 +62,5 @@
 #define NETWORK_PORT 55556
 #define NETWORK_MAX_CONNECTIONS 50
-#define NETWORK_WAIT_TIMEOUT 5000
-#define NETWORK_SEND_WAIT 5
+#define NETWORK_WAIT_TIMEOUT 1
 
   struct ClientList{
@@ -74,8 +74,10 @@
     ConnectionManager();
     ConnectionManager(ClientInformation *head);
+    ConnectionManager(ClientInformation *head, int port);
     ConnectionManager(int port, const char *address, ClientInformation *head);
     ConnectionManager(int port, std::string address, ClientInformation *head);
-    ENetPacket *getPacket(ENetAddress &address); // thread1
-    ENetPacket *getPacket(int &clientID);
+    //ENetPacket *getPacket(ENetAddress &address); // thread1
+    //ENetPacket *getPacket(int &clientID);
+    ENetEvent *getEvent();
     bool queueEmpty();
     void createListener();
@@ -84,23 +86,23 @@
     bool addPacket(ENetPacket *packet, int ID);
     bool addPacketAll(ENetPacket *packet);
-    bool sendPackets(ENetEvent *event);
+  //  bool sendPackets(ENetEvent *event);
     bool sendPackets();
-    bool createClient(int clientID);
+    //bool createClient(int clientID);
     void disconnectClient(ClientInformation *client);
+    void syncClassid(int clientID);
+    bool sendWelcome(int clientID, int shipID, bool allowed);
 
   private:
-    bool clientDisconnect(ENetPeer *peer);
-    bool removeClient(int clientID);
+//     bool clientDisconnect(ENetPeer *peer);
+//     bool removeClient(int clientID);
     bool processData(ENetEvent *event);
-    bool addClient(ENetEvent *event);
+    //bool addClient(ENetEvent *event);
     void receiverThread();
     void disconnectClients();
     int getClientID(ENetPeer peer);
     int getClientID(ENetAddress address);
-    void syncClassid(int clientID);
     ENetPeer *getClientPeer(int clientID);
-    bool createShip(ClientInformation *client);
+    //bool createShip(ClientInformation *client);
     bool removeShip(ClientInformation *client);
-    bool sendWelcome(int clientID, int shipID, bool allowed);
     bool addFakeConnectRequest(ENetEvent *ev);
     PacketBuffer buffer;
@@ -114,4 +116,5 @@
 
     boost::thread *receiverThread_;
+    static boost::recursive_mutex enet_mutex_;
 //     int getNumberOfClients();
     //functions to map what object every clients uses
Index: code/trunk/src/network/GameStateClient.cc
===================================================================
--- code/trunk/src/network/GameStateClient.cc	(revision 1407)
+++ code/trunk/src/network/GameStateClient.cc	(revision 1502)
@@ -21,7 +21,7 @@
  *
  *   Author:
- *      ...
+ *      Oliver Scheuss
  *   Co-authors:
- *      ...
+ *      Dumeni Manatschal
  *
  */
@@ -35,5 +35,4 @@
 #include "Synchronisable.h"
 
-#define GAMESTATEID_INITIAL -1
 
 namespace network
@@ -43,9 +42,11 @@
     int id;
   };
-  
+
   GameStateClient::GameStateClient() {
     COUT(5) << "this: " << this << std::endl;
     last_diff_=0;
     last_gamestate_=GAMESTATEID_INITIAL-1;
+    tempGameState_=NULL;
+    myShip_=NULL;
   }
 
@@ -95,7 +96,9 @@
     return false;
   }
-  
+
   GameStateCompressed *GameStateClient::popPartialGameState(){
     GameState *gs = getPartialSnapshot();
+    if(!gs)
+      return NULL;
     GameStateCompressed *cgs = compress_(gs);
     delete[] gs->data;
@@ -103,5 +106,29 @@
     return cgs;
   }
-  
+
+  void GameStateClient::addGameState(GameStateCompressed *gs){
+    if(tempGameState_!=NULL){
+      //delete the obsolete gamestate
+      if(tempGameState_->id>gs->id)
+        return;
+      delete[] tempGameState_->data;
+      delete tempGameState_;
+    }
+    tempGameState_=gs;
+  }
+  int GameStateClient::processGameState(){
+    if(tempGameState_==NULL)
+      return 0;
+    int id=tempGameState_->id;
+    bool b = saveShipCache();
+    if(pushGameState(tempGameState_)){
+      if(b)
+        loadShipCache();
+      return id;
+    }
+    else
+      return GAMESTATEID_INITIAL;
+  }
+
 
   /**
@@ -151,6 +178,6 @@
           orxonox::Identifier* id = ID((unsigned int)sync.classID);
           if(!id){
-            COUT(4) << "We could not identify a new object; classid: " << sync.classID << std::endl;
-            return false;
+            COUT(3) << "We could not identify a new object; classid: " << sync.classID << " uint: " << (unsigned int)sync.classID << " objectID: " << sync.objectID << " size: " << sync.length << std::endl;
+            return false; // most probably the gamestate is corrupted
           }
           Synchronisable *no = dynamic_cast<Synchronisable *>(id->fabricate());
@@ -168,5 +195,7 @@
           }
           if( !no->create() )
+          {
             COUT(1) << "We couldn't manifest (create() ) the object: " << sync.objectID << std::endl;
+          }
           it=orxonox::ObjectList<Synchronisable>::end();
         }
@@ -174,6 +203,8 @@
         // we have our object
         if(! it->updateData(sync))
+        {
           COUT(1) << "We couldn't update objectID: " \
           << sync.objectID << "; classID: " << sync.classID << std::endl;
+        }
       }
       ++it;
@@ -213,4 +244,6 @@
     }
     //retval->data = (unsigned char*)malloc(size);
+    if(size==0)
+      return NULL;
     retval->data = new unsigned char[size];
     if(!retval->data){
@@ -245,6 +278,6 @@
     return retval;
   }
-  
-  
+
+
   GameState *GameStateClient::undiff(GameState *old, GameState *diff) {
     if(!old || !diff)
@@ -253,9 +286,11 @@
     int of=0; // pointers offset
     int dest_length=0;
-    if(old->size>=diff->size)
+    /*if(old->size>=diff->size)
       dest_length=old->size;
-    else
+    else*/
       dest_length=diff->size;
 //     unsigned char *dp = (unsigned char *)malloc(dest_length*sizeof(unsigned char));
+    if(dest_length==0)
+      return NULL;
     unsigned char *dp = new unsigned char[dest_length*sizeof(unsigned char)];
     while(of<old->size && of<diff->size){
@@ -270,10 +305,10 @@
           of++;
         }
-      } else{
+      } /*else{
         while(of<dest_length){
           *(dp+of)=*(ap+of)^n;
           of++;
         }
-      }
+      }*/
     }
     // should be finished now
@@ -297,4 +332,6 @@
 
     uLongf buffer = (uLongf)((a->size + 12)*1.01)+1;
+    if(buffer==0)
+      return NULL;
     unsigned char *dest = new unsigned char[buffer];
     int retval;
@@ -303,5 +340,5 @@
     switch ( retval ) {
       case Z_OK: COUT(5) << "G.St.Cl: compress: successfully compressed" << std::endl; break;
-      case Z_MEM_ERROR: COUT(1) << "G.St.Cl: compress: not enough memory available in gamestate.compress" << std::endl; 
+      case Z_MEM_ERROR: COUT(1) << "G.St.Cl: compress: not enough memory available in gamestate.compress" << std::endl;
       return NULL;
       case Z_BUF_ERROR: COUT(2) << "G.St.Cl: compress: not enough memory available in the buffer in gamestate.compress" << std::endl;
@@ -321,6 +358,6 @@
     return compressedGamestate;
   }
-  
-  
+
+
   GameState *GameStateClient::decompress(GameStateCompressed *a) {
     //COUT(4) << "GameStateClient: uncompressing gamestate. id: " << a->id << ", baseid: " << a->base_id << ", normsize: " << a->normsize << ", compsize: " << a->compsize << std::endl;
@@ -333,4 +370,6 @@
       bufsize = normsize;
 //     unsigned char* dest = (unsigned char*)malloc( bufsize );
+    if(bufsize==0)
+      return NULL;
     unsigned char *dest = new unsigned char[bufsize];
     int retval;
@@ -376,5 +415,5 @@
     return t;
   }
-  
+
   void GameStateClient::cleanup(){
     std::map<int, GameState*>::iterator temp, it = gameStateMap.begin();
@@ -388,4 +427,5 @@
       gameStateMap.erase(temp);
     }
+    tempGameState_=NULL;
   }
 
@@ -397,19 +437,44 @@
     }
     COUT(4) << std::endl;
-    
-  }
-  
-  
+
+  }
+
+  bool GameStateClient::saveShipCache(){
+    if(myShip_==NULL)
+      myShip_ = orxonox::SpaceShip::getLocalShip();
+    if(myShip_){
+      //      unsigned char *data = new unsigned char[myShip_->getSize()];
+      int size=myShip_->getSize(0x3);
+      if(size==0)
+        return false;
+      unsigned char *data = new unsigned char [size];
+      shipCache_ = myShip_->getData(data, 0x1);
+      return true;
+    }else
+      return false;
+  }
+
+  bool GameStateClient::loadShipCache(){
+    if(myShip_){
+      myShip_->updateData(shipCache_, 0x2);
+      if(shipCache_.data){
+        delete[] shipCache_.data;
+      }
+      return true;
+    }else
+      return false;
+  }
+
     //##### ADDED FOR TESTING PURPOSE #####
   GameState* GameStateClient::testDecompress( GameStateCompressed* gc ) {
     return decompress( gc );
   }
-  
+
   GameState* GameStateClient::testUndiff( GameState* g_old, GameState* g_diffed ) {
     return undiff( g_old, g_diffed );
   }
   //##### ADDED FOR TESTING PURPOSE #####
-  
-  
+
+
 }
 
Index: code/trunk/src/network/GameStateClient.h
===================================================================
--- code/trunk/src/network/GameStateClient.h	(revision 1407)
+++ code/trunk/src/network/GameStateClient.h	(revision 1502)
@@ -21,7 +21,7 @@
  *
  *   Author:
- *      ...
+ *      Oliver Scheuss
  *   Co-authors:
- *      ...
+ *      Dumeni Manatschal
  *
  */
@@ -33,5 +33,5 @@
 //
 //
-// Author:  <>, (C) 2007
+// Author:  Oliver Scheuss, (C) 2007
 //
 // Copyright: See COPYING file that comes with this distribution
@@ -46,5 +46,8 @@
 #include "core/CorePrereqs.h"
 #include "PacketTypes.h"
+#include "objects/SpaceShip.h"
 
+
+#define GAMESTATEID_INITIAL -1
 
 namespace network
@@ -56,10 +59,12 @@
     ~GameStateClient();
     
+    void addGameState(GameStateCompressed *gs);
+    int processGameState();
+    GameStateCompressed *popPartialGameState();
+    void cleanup();
+  private:
     bool pushGameState(GameStateCompressed *compstate);
-    GameStateCompressed *popPartialGameState();
-  private:
     bool loadSnapshot(GameState *state);
     GameState *getPartialSnapshot();
-    void cleanup();
     GameState *undiff(GameState *old, GameState *diff);
     GameStateCompressed *compress_(GameState *a);
@@ -69,8 +74,13 @@
     void removeObject(orxonox::Iterator<Synchronisable> &it);
     void printGameStateMap();
+    bool saveShipCache();
+    bool loadShipCache();
 
     int           last_diff_;
     int           last_gamestate_;
     std::map<int, GameState *> gameStateMap;
+    GameStateCompressed *tempGameState_; // we save the received gamestates here during processQueue
+    orxonox::SpaceShip *myShip_;
+    syncData shipCache_;
     
     
Index: code/trunk/src/network/GameStateManager.cc
===================================================================
--- code/trunk/src/network/GameStateManager.cc	(revision 1407)
+++ code/trunk/src/network/GameStateManager.cc	(revision 1502)
@@ -68,4 +68,27 @@
     printGameStates();
     return;
+  }
+  
+  void GameStateManager::addGameState(GameStateCompressed *gs, int clientID){
+    if(!gs)
+      return;
+    std::map<int, GameStateCompressed*>::iterator it = gameStateQueue.find(clientID);
+    if(it!=gameStateQueue.end()){
+      // delete obsolete gamestate
+      delete[] it->second->data;
+      delete it->second;
+    }
+    gameStateQueue[clientID] = gs;
+    return;
+  }
+  
+  void GameStateManager::processGameStates(){
+    std::map<int, GameStateCompressed*>::iterator it;
+    // now push only the most recent gamestates we received (ignore obsolete ones)
+    for(it = gameStateQueue.begin(); it!=gameStateQueue.end(); it++){
+      pushGameState(it->second, it->first);
+    }
+    // now clear the queue
+    gameStateQueue.clear();
   }
   
@@ -117,5 +140,5 @@
         client = it->second;
       GameState *server = reference;
-      COUT(3) << "client: " << client << " server: " << server << " gamestatemap: " << &gameStateMap << std::endl;
+      COUT(4) << "client: " << client << " server: " << server << " gamestatemap: " << &gameStateMap << " size: " << server->size << std::endl;
       if(client)
         return encode(client, server);
@@ -170,4 +193,6 @@
     }
     //retval->data = (unsigned char*)malloc(size);
+    if(size==0)
+      return NULL;
     retval->data = new unsigned char[size];
     if(!retval->data){
@@ -237,4 +262,6 @@
       data+=sizeof(int);
       sync.classID = *(int*)data;
+      if(sync.classID == 0) // TODO: remove this
+        COUT(3) << "received a classid 0" << std::endl;
       data+=sizeof(int);
       sync.data = data;
@@ -246,5 +273,5 @@
 
       if(!it){
-        // the object does not exist yet
+        // the objectaber ich glaub die  does not exist yet
         COUT(4) << "loadsnapshot: creating new object " << std::endl;
         //COUT(4) << "loadSnapshot:\tclassid: " << sync.classID << ", name: " << ID((unsigned int) sync.classID)->getName() << std::endl;
@@ -314,38 +341,40 @@
   }
 
-  GameState *GameStateManager::diff(GameState *a, GameState *b) {
-    unsigned char *ap = a->data, *bp = b->data;
+  GameState *GameStateManager::diff(GameState *alt, GameState *neu) {
+    unsigned char *ap = alt->data, *bp = neu->data;
     int of=0; // pointers offset
     int dest_length=0;
-    if(a->size>=b->size)
-      dest_length=a->size;
-    else
-      dest_length=b->size;
+    /*if(alt->size>neu->size)
+      dest_length=alt->size;
+    else*/
+      dest_length=neu->size;
+    if(dest_length==0)
+      return NULL;
     //unsigned char *dp = (unsigned char *)malloc(dest_length*sizeof(unsigned char));
     unsigned char *dp = new unsigned char[dest_length*sizeof(unsigned char)];
-    while(of<a->size && of<b->size){
+    while(of<alt->size && of<neu->size){
       *(dp+of)=*(ap+of)^*(bp+of); // do the xor
       ++of;
     }
-    if(a->size!=b->size){ // do we have to fill up ?
+    if(alt->size!=neu->size){ // do we have to fill up ?
       unsigned char n=0;
-      if(a->size<b->size){
+      if(alt->size<neu->size){
         while(of<dest_length){
           *(dp+of)=n^*(bp+of);
           of++;
         }
-      } else{
+      } /*else{
         while(of<dest_length){
           *(dp+of)=*(ap+of)^n;
           of++;
         }
-      }
+      }*/
     }
 
     GameState *r = new GameState;
-    r->id = b->id;
+    r->id = neu->id;
     r->size = dest_length;
     r->diffed = true;
-    r->base_id = a->id;
+    r->base_id = alt->id;
     r->data = dp;
     r->complete = true;
@@ -362,4 +391,6 @@
     //COUT(4) << "size: " << size << ", buffer: " << buffer << std::endl;
     //unsigned char* dest = (unsigned char*)malloc( buffer );
+    if(buffer==0)
+      return NULL;
     unsigned char *dest = new unsigned char[buffer];
     //COUT(4) << "dest: " << dest << std::endl;
@@ -404,4 +435,6 @@
       bufsize = normsize;
 //     unsigned char* dest = (unsigned char*)malloc( bufsize );
+    if(bufsize==0)
+      return NULL;
     unsigned char *dest = new unsigned char[bufsize];
     int retval;
@@ -436,4 +469,11 @@
       return;
     int curid = temp->getGamestateID();
+    
+    if(gamestateID == GAMESTATEID_INITIAL){
+      temp->setGameStateID(GAMESTATEID_INITIAL);
+      if(curid!=GAMESTATEID_INITIAL)
+        --(gameStateUsed.find(curid)->second);
+      return;
+    }
     if(curid > gamestateID)
       // the network packets got messed up 
@@ -446,5 +486,5 @@
       --(gameStateUsed.find(curid)->second);
     ++(gameStateUsed.find(gamestateID)->second);
-    temp->setGamestateID(gamestateID);
+    temp->setGameStateID(gamestateID);
     /*
     GameState *old = clientGameState[clientID];
Index: code/trunk/src/network/GameStateManager.h
===================================================================
--- code/trunk/src/network/GameStateManager.h	(revision 1407)
+++ code/trunk/src/network/GameStateManager.h	(revision 1502)
@@ -72,10 +72,13 @@
     ~GameStateManager();
     
+    void addGameState(GameStateCompressed *gs, int clientID);
+    void processGameStates();
+    
     void update();
     GameStateCompressed *popGameState(int clientID);
-    bool pushGameState(GameStateCompressed *gs, int clientID);
     void ackGameState(int clientID, int gamestateID);
     void removeClient(ClientInformation *client);
-  private:
+    private:
+    bool pushGameState(GameStateCompressed *gs, int clientID);
     void cleanup(); // "garbage handler"
     GameState *getSnapshot();
@@ -83,5 +86,5 @@
     GameStateCompressed *encode(GameState *a, GameState *b);
     GameStateCompressed *encode(GameState *a);
-    GameState *diff(GameState *a, GameState *b);
+    GameState *diff(GameState *alt, GameState *neu);
     GameStateCompressed *compress_(GameState *a);
     GameState *decompress(GameStateCompressed *a);
@@ -91,4 +94,5 @@
     std::map<int, GameState*> gameStateMap; //map gsID to gamestate*
     std::map<int, int> gameStateUsed; // save the number of clients, that use the specific gamestate
+    std::map<int, GameStateCompressed*> gameStateQueue;
     GameState *reference;
     ClientInformation *head_;
Index: code/trunk/src/network/NetworkPrereqs.h
===================================================================
--- code/trunk/src/network/NetworkPrereqs.h	(revision 1407)
+++ code/trunk/src/network/NetworkPrereqs.h	(revision 1502)
@@ -35,5 +35,5 @@
 #define _NetworkPrereqs_H__
 
-#include "OrxonoxPlatform.h"
+#include "util/OrxonoxPlatform.h"
 
 //-----------------------------------------------------------------------
@@ -54,20 +54,4 @@
 #else
 #  define _NetworkExport
-#endif
-
-//-----------------------------------------------------------------------
-// fixed width integers
-//-----------------------------------------------------------------------
-#if ORXONOX_COMPILER == 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;
-#else
-# include "inttypes.h"
 #endif
 
Index: code/trunk/src/network/PacketBuffer.cc
===================================================================
--- code/trunk/src/network/PacketBuffer.cc	(revision 1407)
+++ code/trunk/src/network/PacketBuffer.cc	(revision 1502)
@@ -62,6 +62,5 @@
       last->next=NULL;
       // change this!!!!!!!  ---- we are not doing stl so we won't change this
-      last->packet = ev->packet;
-      last->address = ev->peer->address;
+      last->event = ev;
       //last->address = ev->peer->address;
     } else {
@@ -72,6 +71,5 @@
       last->next=NULL;
       // save the packet to the new element
-      last->packet = ev->packet;
-      last->address = ev->peer->address;
+      last->event = ev;
       //last->address = ev->peer->address;
     }
@@ -82,10 +80,10 @@
   //returns the first element in the list without deleting it but
   //moving first pointer to next element
-  ENetPacket *PacketBuffer::pop() {
+  /*ENetPacket *PacketBuffer::pop() {
     ENetAddress address;
     return pop(address);
-  }
-
-  ENetPacket *PacketBuffer::pop(ENetAddress &address) {
+  }*/
+  
+  ENetEvent *PacketBuffer::pop(){
     boost::recursive_mutex::scoped_lock lock(mutex_);
     //std::cout << "packetbuffer pop(address)" << std::endl;
@@ -93,6 +91,26 @@
       QueueItem *temp = first;
       // get packet
-      ENetPacket *pck=first->packet;
-      address = first->address;
+      ENetEvent *ev=first->event;
+      //address = first->address;
+      // remove first element
+      first = first->next;
+      delete temp;
+      lock.unlock();
+      //std::cout << "pop(address) size of packet " << pck->dataLength << std::endl;
+      return ev;
+    } else{
+      lock.unlock();
+      return NULL;
+    }
+  }
+
+  /*ENetPacket *PacketBuffer::pop(ENetAddress &address) {
+    boost::recursive_mutex::scoped_lock lock(mutex_);
+    //std::cout << "packetbuffer pop(address)" << std::endl;
+    if(first!=NULL ){
+      QueueItem *temp = first;
+      // get packet
+      ENetPacket *pck=first->event->packet;
+      address = first->event->peer->address;
       // remove first element
       first = first->next;
@@ -105,5 +123,5 @@
       return NULL;
     }
-  }
+  }*/
 
   bool PacketBuffer::isEmpty() {
Index: code/trunk/src/network/PacketBuffer.h
===================================================================
--- code/trunk/src/network/PacketBuffer.h	(revision 1407)
+++ code/trunk/src/network/PacketBuffer.h	(revision 1502)
@@ -55,6 +55,6 @@
 
   struct QueueItem{
-    ENetPacket *packet;
-    ENetAddress address;
+    ENetEvent *event;
+    //ENetAddress address;
     QueueItem *next;
   };
@@ -68,6 +68,7 @@
     void print();
     // pops a packet from the queue
-    ENetPacket *pop();
-    ENetPacket *pop(ENetAddress &address);
+    //ENetPacket *pop();
+    //ENetPacket *pop(ENetAddress &address);
+    ENetEvent *pop();
     // pushs a packet to the queue
     bool push(ENetEvent *ev);
Index: code/trunk/src/network/PacketDecoder.cc
===================================================================
--- code/trunk/src/network/PacketDecoder.cc	(revision 1407)
+++ code/trunk/src/network/PacketDecoder.cc	(revision 1502)
@@ -68,10 +68,4 @@
     case COMMAND:
       return command( packet, clientId );
-    case MOUSE:
-      mousem( packet, clientId );
-      return true;
-    case KEYBOARD:
-      keystrike( packet, clientId );
-      return true;
     case CHAT:
       chatMessage( packet, clientId );
@@ -90,5 +84,5 @@
     return false;
   }
-  
+
   bool PacketDecoder::testAndRemoveCRC(ENetPacket *packet){
     uint32_t submittetcrc;
@@ -108,5 +102,5 @@
     return false;
   }
-  
+
   // ATTENTION: TODO watch, that arguments we pass over to the processFunction gets deleted in THE PROCESSXXX function
 
@@ -124,7 +118,9 @@
     enet_packet_destroy( packet );
   }
-  
+
   bool PacketDecoder::command( ENetPacket* packet, int clientId ){
     int length = *(int*)((unsigned char *)packet->data+sizeof(int));
+    if(length<=0)
+      return false;
     void *data = (void *)new unsigned char[length];
     memcpy(data, (void *)(packet->data+2*sizeof(int)), length);
@@ -133,29 +129,9 @@
   }
 
-  void PacketDecoder::mousem( ENetPacket* packet, int clientId )
-  {
-    mouse* mouseMove = new mouse;
-    //copy data of packet->data to new struct
-    *mouseMove = *(mouse*)packet->data;
-
-    //clean memory
-    enet_packet_destroy( packet );
-    printMouse( mouseMove ); //debug info
-  }
-
-  void PacketDecoder::keystrike( ENetPacket* packet, int clientId )
-  {
-    keyboard* key = new keyboard;
-    *key = *(keyboard*)packet->data; //see above
-
-    //clean memory
-    enet_packet_destroy( packet );
-    printKey( key ); //debug info
-
-  }
-
   void PacketDecoder::chatMessage( ENetPacket* packet, int clientId )
   {
     chat* chatting = new chat;
+    if(packet->dataLength==4)
+      return;
     chatting->id = (int)*packet->data; //first copy id into new struct
     //since the chat message is a char*, allocate the memory needed
@@ -185,7 +161,4 @@
       return;
     }
-    //since it's not alowed to use void* for pointer arithmetic
-    //FIXME: variable never used
-    unsigned char* data = (unsigned char *)(packet->data);
     //copy the GameStateCompressed id into the struct, which is located at second place data+sizeof( int )
     memcpy( (void*)&(currentState->id), (const void*)(packet->data+1*sizeof( int )), sizeof( int) );
@@ -202,9 +175,15 @@
     //since data is not allocated, because it's just a pointer, allocate it with size of gamestatedatastream
     if(currentState->compsize==0)
+    {
       COUT(2) << "PacketDecoder: compsize is 0" << std::endl;
+    }
 //     currentState->data = (unsigned char*)(malloc( currentState->compsize ));
+    if(currentState->compsize==0)
+      return;
     currentState->data = new unsigned char[currentState->compsize];
     if(currentState->data==NULL)
+    {
       COUT(2) << "PacketDecoder: Gamestatepacket-decoder: memory leak" << std::endl;
+    }
     //copy the GameStateCompressed data
     memcpy( (void*)(currentState->data), (const void*)(packet->data+5*sizeof( int ) + 2*sizeof(bool)), currentState->compsize );
@@ -221,4 +200,6 @@
     cid->id = ((classid *)(packet->data))->id;
     cid->clid = ((classid *)(packet->data))->clid;
+    if(cid->length==0)
+      return;
 //     cid->message = (const char *)malloc(cid->length);
     cid->message = new char[cid->length];
@@ -229,6 +210,6 @@
     processClassid(cid);
   }
-  
-  
+
+
   bool PacketDecoder::decodeWelcome( ENetPacket* packet, int clientID ){
     welcome *w = new welcome;
@@ -240,5 +221,5 @@
     return processWelcome(w);
   }
-  
+
   bool PacketDecoder::decodeConnectRequest( ENetPacket *packet, int clientID ){
     connectRequest *con = new connectRequest;
@@ -279,10 +260,10 @@
     return;
   }
-  
+
   bool PacketDecoder::processWelcome( welcome *w ){
     delete w;
     return true;
   }
-  
+
   bool PacketDecoder::processConnectRequest( connectRequest *con, int clientID ){
     COUT(3) << "packetdecoder: processing connectRequest" << std::endl;
@@ -299,20 +280,11 @@
   }
 
-  void PacketDecoder::printMouse( mouse* data )
-  {
-    COUT(5) << "data id: " << data->id << std::endl;
-    COUT(5) << "data:    " << data->x << " " << data->y << std::endl;
-  }
-
-  void PacketDecoder::printKey( keyboard* data )
-  {
-    COUT(5) << "data id: " << data->id << std::endl;
-    COUT(5) << "data:    " << (char)data->press << std::endl;
-  }
 
   void PacketDecoder::printChat( chat* data, int clientId )
   {
     if(clientId!=CLIENTID_CLIENT)
+    {
       COUT(5) << "client: " << clientId << std::endl;
+    }
     COUT(5) << "data id: " << data->id << std::endl;
     COUT(5) << "data:    " << data->message << std::endl;
Index: code/trunk/src/network/PacketGenerator.cc
===================================================================
--- code/trunk/src/network/PacketGenerator.cc	(revision 1407)
+++ code/trunk/src/network/PacketGenerator.cc	(revision 1502)
@@ -78,10 +78,10 @@
   {
     COUT(4) << "PacketGenerator: generating new acknowledgement, id: " << state << std::endl;
-    ack* ackreq = new ack;
+    
+    ENetPacket *packet = enet_packet_create( NULL , sizeof( ack ), reliable );
+    ack* ackreq = (ack *)packet->data;
     ackreq->id = ACK;
     ackreq->a = state;
-
-    ENetPacket *packet = enet_packet_create( ackreq , sizeof( *ackreq ), reliable );
-    delete ackreq;
+    //delete ackreq;
     return packet;
   }
@@ -89,4 +89,6 @@
   ENetPacket* command( int dataLength, void *data, int reliable = ENET_PACKET_FLAG_RELIABLE )
   {
+    if(dataLength==0)
+      return NULL;
     unsigned char *stream = new unsigned char[dataLength + 2*sizeof(int)];
     if(!stream)
@@ -101,30 +103,4 @@
   }
 
-  /*### mouseupdates */
-  ENetPacket* PacketGenerator::mousem( double x, double y, int reliable )
-  {
-    COUT(4) << "PacketGenerator: generating new mouse" << std::endl;
-    mouse* mousemove = new mouse;
-    mousemove->id = MOUSE;
-    mousemove->x = x;
-    mousemove->y = y;
-
-    ENetPacket *packet = enet_packet_create( mousemove , sizeof( *mousemove ), reliable );
-    delete mousemove;
-    return packet;
-  }
-
-  /*### keystrikes updates */
-  ENetPacket* PacketGenerator::keystrike( char press, int reliable )
-  {
-    COUT(4) << "PacketGenerator: generating new keyboard" << std::endl;
-    keyboard* key = new keyboard;
-    key->id = KEYBOARD;
-    key->press = press;
-
-    ENetPacket *packet = enet_packet_create( key , sizeof( *key ), reliable );
-    delete key;
-    return packet;
-  }
 
   /*### chat messages packet */
@@ -150,5 +126,9 @@
     //std::cout << "totalLen " << totalLen << std::endl;
     //unsigned char *data = (unsigned char*)malloc( totalLen ); //allocate the memory for datastream
-    unsigned char *data = new unsigned char[totalLen];
+    if(totalLen==0)
+      return NULL;
+    ENetPacket *packet = enet_packet_create( NULL , totalLen+sizeof(uint32_t), reliable );
+    //unsigned char *data = new unsigned char[totalLen];
+    unsigned char *data = packet->data;
     memcpy( (void*)(data), (const void*)&gid, sizeof( int ) ); //this is the enet id
     memcpy( (void*)(data+sizeof(int)), (const void*)&(states->id), sizeof(int) ); //the GameStateCompressed id
@@ -163,6 +143,5 @@
     //create an enet packet with the generated bytestream
     COUT(4) << "PacketGenerator generating totalLen " << totalLen << std::endl;
-    ENetPacket *packet = enet_packet_create( data , totalLen, reliable );
-    delete[] data;
+    //delete[] data;
     if(!addCRC(packet))
       COUT(3) << "could not add crc to gamestate packet" << std::endl;
@@ -173,4 +152,6 @@
   {
     //unsigned char* data = (unsigned char *)malloc(3*sizeof(int)+classname.length()+1);
+    if(classname.length()==0)
+      return NULL;
     unsigned char *data = new unsigned char[3*sizeof(int)+classname.length()+1];
     std::cout << "PacketGenerator: classid: " << classid << ", name: " << classname << std::endl;
@@ -206,14 +187,14 @@
   bool PacketGenerator::addCRC( ENetPacket *packet){
     unsigned char *data = packet->data;
-    uint32_t crc32=calcCRC(data, packet->dataLength);
+    uint32_t crc32=calcCRC(data, packet->dataLength-sizeof(uint32_t));
     // now append the crc to the packet data
-    int oldlength = packet->dataLength;
-    if(enet_packet_resize(packet, packet->dataLength+sizeof(uint32_t))==0){
+    int oldlength = packet->dataLength-sizeof(uint32_t);
+    //if(enet_packet_resize(packet, packet->dataLength+sizeof(uint32_t))==0){
       memcpy(&packet->data[oldlength], &crc32, sizeof(uint32_t));
       return true;
-    }else{
-      COUT(3) << "could not add crc to gamestate" << std::endl;
-      return false;
-    }
+    //}else{
+     // COUT(3) << "could not add crc to gamestate" << std::endl;
+     // return false;
+    //}
   }
 
Index: code/trunk/src/network/PacketManager.h
===================================================================
--- code/trunk/src/network/PacketManager.h	(revision 1407)
+++ code/trunk/src/network/PacketManager.h	(revision 1502)
@@ -59,6 +59,4 @@
     ENetPacket* acknowledgement( int state, int reliable = 0 ); // we do not want reliability
     ENetPacket* command( int dataLength, void *data, int reliable = ENET_PACKET_FLAG_RELIABLE );
-    ENetPacket* mousem( double x, double y, int reliable = ENET_PACKET_FLAG_RELIABLE );
-    ENetPacket* keystrike( char press, int reliable = ENET_PACKET_FLAG_RELIABLE );
     ENetPacket* chatMessage( const char* message, int reliable = ENET_PACKET_FLAG_RELIABLE );
     ENetPacket* gstate( GameStateCompressed *states, int reliable = 0 ); // we do not want reliability of gamestates
@@ -94,6 +92,4 @@
     void acknowledgement( ENetPacket* packet, int clientId = CLIENTID_CLIENT );
     bool command( ENetPacket* packet, int clientId );
-    void mousem( ENetPacket* packet, int clientId = CLIENTID_CLIENT );
-    void keystrike( ENetPacket* packet, int clientId = CLIENTID_CLIENT );
     void chatMessage( ENetPacket* packet, int clientId = CLIENTID_CLIENT );
     void gstate( ENetPacket* packet, int clientID = CLIENTID_CLIENT );
@@ -113,6 +109,4 @@
     //print functions
     void printAck( ack* data );
-    void printMouse( mouse* data );
-    void printKey( keyboard* data );
     void printChat( chat* data, int clientId );
     void printGamestate( GameStateCompressed *data );
Index: code/trunk/src/network/PacketTypes.h
===================================================================
--- code/trunk/src/network/PacketTypes.h	(revision 1407)
+++ code/trunk/src/network/PacketTypes.h	(revision 1502)
@@ -48,7 +48,5 @@
   enum packet_id {
     ACK,
-    MOUSE,
     COMMAND,
-    KEYBOARD,
     CHAT,
     GAMESTATE ,
@@ -104,14 +102,4 @@
   };
 
-  struct mouse {
-    int id;
-    double x;
-    double y;
-  };
-
-  struct keyboard {
-    int id;
-    char press;
-  };
   //only in this class, not PacketGenerator, used as pattern to put incoming
   //bytes inside
Index: code/trunk/src/network/Server.cc
===================================================================
--- code/trunk/src/network/Server.cc	(revision 1407)
+++ code/trunk/src/network/Server.cc	(revision 1502)
@@ -42,4 +42,5 @@
 
 #include <iostream>
+
 
 #include "ConnectionManager.h"
@@ -49,4 +50,5 @@
 //#include "NetworkFrameListener.h"
 #include "util/Sleep.h"
+#include "objects/SpaceShip.h"
 
 
@@ -56,5 +58,5 @@
   
 #define MAX_FAILURES 20;
-  
+#define NETWORK_FREQUENCY 30
   
   /**
@@ -63,4 +65,5 @@
   */
   Server::Server() {
+    timeSinceLastUpdate_=0;
     packet_gen = PacketGenerator();
     clients = new ClientInformation(true);
@@ -68,4 +71,12 @@
     gamestates = new GameStateManager(clients);
   }
+  
+  Server::Server(int port){
+    timeSinceLastUpdate_=0;
+    packet_gen = PacketGenerator();
+    clients = new ClientInformation(true);
+    connection = new ConnectionManager(clients, port);
+    gamestates = new GameStateManager(clients);
+  }
 
   /**
@@ -75,4 +86,5 @@
   */
   Server::Server(int port, std::string bindAddress) {
+    timeSinceLastUpdate_=0;
     packet_gen = PacketGenerator();
     clients = new ClientInformation();
@@ -87,4 +99,5 @@
   */
   Server::Server(int port, const char *bindAddress) {
+    timeSinceLastUpdate_=0;
     packet_gen = PacketGenerator();
     clients = new ClientInformation();
@@ -117,9 +130,5 @@
     ENetPacket *packet = packet_gen.chatMessage(msg.c_str());
     //std::cout <<"adding packets" << std::endl;
-    if(connection->addPacketAll(packet))
-    //std::cout <<"added packets" << std::endl;
-      return connection->sendPackets();
-    else
-      return false;
+    return connection->addPacketAll(packet);
   }
 
@@ -132,11 +141,5 @@
     ENetPacket *packet = packet_gen.chatMessage(msg);
     COUT(4) <<"Server: adding Packets" << std::endl;
-    connection->addPacketAll(packet);
-    //std::cout <<"added packets" << std::endl;
-    if (connection->sendPackets()){
-      COUT(4) << "Server: Sucessfully" << std::endl;
-      return true;
-    }
-    return false;
+    return connection->addPacketAll(packet);
   }
 
@@ -148,6 +151,12 @@
   void Server::tick(float time) {
     processQueue();
-    updateGamestate();
-//     usleep(500000); // TODO remove
+    //this steers our network frequency
+    timeSinceLastUpdate_+=time;
+    if(timeSinceLastUpdate_>=(1./NETWORK_FREQUENCY)){
+      timeSinceLastUpdate_-=(1./NETWORK_FREQUENCY);
+      gamestates->processGameStates();
+      updateGamestate();
+    }
+//     usleep(5000); // TODO remove
     return;
   }
@@ -157,15 +166,32 @@
   */
   void Server::processQueue() {
-    ENetPacket *packet;
+    ENetEvent *event;
     int clientID=-1;
     while(!connection->queueEmpty()){
       //std::cout << "Client " << clientID << " sent: " << std::endl;
       //clientID here is a reference to grab clientID from ClientInformation
-      packet = connection->getPacket(clientID);
-      if(!packet)
-        continue;
+      event = connection->getEvent();
+      if(!event)
+        continue;
+      assert(event->type != ENET_EVENT_TYPE_NONE);
+      switch( event->type ) {
+      case ENET_EVENT_TYPE_CONNECT:
+        COUT(3) << "processing event_Type_connect" << std::endl;
+        addClient(event);
+        break;
+      case ENET_EVENT_TYPE_DISCONNECT:
+        if(clients->findClient(&event->peer->address))
+          disconnectClient(event);
+        break;
+      case ENET_EVENT_TYPE_RECEIVE:
+        if(clients->findClient(&event->peer->address)){
+          clientID = clients->findClient(&event->peer->address)->getID();
+          if( !elaborate(event->packet, clientID) ) 
+            COUT(3) << "Server: could not elaborate" << std::endl;
+        }
+        break;
+      }
+      delete event;
       //if statement to catch case that packetbuffer is empty
-      if( !elaborate(packet, clientID) ) 
-        COUT(3) << "Server: could not elaborate" << std::endl;
     }
   }
@@ -210,14 +236,18 @@
       if(gs==NULL){
         COUT(2) << "Server: could not generate gamestate (NULL from compress)" << std::endl;
-        return false;
+        continue;
       }
       //std::cout << "adding gamestate" << std::endl;
-      if ( !(connection->addPacket(packet_gen.gstate(gs), cid)) ){
+      ENetPacket *packet = packet_gen.gstate(gs);
+      if(!packet)
+	continue;
+      if ( !(connection->addPacket(packet, cid)) ){
         COUT(3) << "Server: packet with client id (cid): " << cid << " not sended: " << temp->getFailures() << std::endl; 
         temp->addFailure();
-        if(temp->getFailures() > 20 )
-          disconnectClient(temp);
+        /*if(temp->getFailures() > 0 )
+          disconnectClient(temp);*/
       //std::cout << "added gamestate" << std::endl;
-      }
+      }else
+        temp->resetFailures();
       added=true;
       temp=temp->next();
@@ -226,14 +256,14 @@
       delete gs;
     }
-    if(added) {
+    /*if(added) {
       //std::cout << "send gamestates from server.cc in sendGameState" << std::endl;
       return connection->sendPackets();
-    }
-    COUT(5) << "Server: had no gamestates to send" << std::endl;
-    return false;
+    }*/
+    //COUT(5) << "Server: had no gamestates to send" << std::endl;
+    return true;
   }
 
   void Server::processAck( ack *data, int clientID) {
-    COUT(4) << "\b\b\b\n\n\n\n\nServer: processing ack from client: " << clientID << "; ack-id: " << data->a << std::endl;
+    COUT(4) << "Server: processing ack from client: " << clientID << "; ack-id: " << data->a << std::endl;
     gamestates->ackGameState(clientID, data->a);
     delete data;
@@ -241,7 +271,7 @@
   
   bool Server::processConnectRequest( connectRequest *con, int clientID ){
-    COUT(3) << "processing connectRequest " << std::endl;
+    //(COUT(3) << "processing connectRequest " << std::endl;
     //connection->addPacket(packet_gen.gstate(gamestates->popGameState(clientID)) , clientID);
-    connection->createClient(clientID);
+    //createClient(clientID);
     delete con;
     return true;
@@ -250,9 +280,96 @@
   void Server::processGamestate( GameStateCompressed *data, int clientID){
     COUT(4) << "processing partial gamestate from client " << clientID << std::endl;
-    if(!gamestates->pushGameState(data, clientID))
-        COUT(3) << "Could not push gamestate\t\t\t\t=====" << std::endl;
+    gamestates->addGameState(data, clientID);
+        /*COUT(3) << "Could not push gamestate\t\t\t\t=====" << std::endl;
     else
       if(clients->findClient(clientID))
-        clients->findClient(clientID)->resetFailures();
+        clients->findClient(clientID)->resetFailures();*/
+  }
+  
+  bool Server::addClient(ENetEvent *event){
+    ClientInformation *temp = clients->insertBack(new ClientInformation);
+    if(!temp){
+      COUT(2) << "Server: could not add client" << std::endl;
+      return false;
+    }
+    if(temp->prev()->getHead()) { //not good if you use anything else than insertBack
+      temp->prev()->setID(0); //bugfix: not necessary but usefull
+      temp->setID(1);
+    }
+    else
+      temp->setID(temp->prev()->getID()+1);
+    temp->setPeer(event->peer);
+    COUT(3) << "Server: added client id: " << temp->getID() << std::endl;
+    return createClient(temp->getID());
+  }
+  
+  bool Server::createClient(int clientID){
+    ClientInformation *temp = clients->findClient(clientID);
+    if(!temp){
+      COUT(2) << "Conn.Man. could not create client with id: " << clientID << std::endl;
+      return false;
+    }
+    COUT(4) << "Con.Man: creating client id: " << temp->getID() << std::endl;
+    connection->syncClassid(temp->getID());
+    COUT(4) << "creating spaceship for clientid: " << temp->getID() << std::endl;
+    // TODO: this is only a hack, untill we have a possibility to define default player-join actions
+    if(!createShip(temp))
+      COUT(2) << "Con.Man. could not create ship for clientid: " << clientID << std::endl;
+    else
+      COUT(3) << "created spaceship" << std::endl;
+    temp->setSynched(true);
+    COUT(3) << "sending welcome" << std::endl;
+    connection->sendWelcome(temp->getID(), temp->getShipID(), true);
+    return true;
+  }
+  
+  bool Server::createShip(ClientInformation *client){
+    if(!client)
+      return false;
+    orxonox::Identifier* id = ID("SpaceShip");
+    if(!id){
+      COUT(4) << "We could not create the SpaceShip for client: " << client->getID() << std::endl;
+      return false;
+    }
+    orxonox::SpaceShip *no = dynamic_cast<orxonox::SpaceShip *>(id->fabricate());
+    no->setPosition(orxonox::Vector3(0,0,80));
+    no->setScale(10);
+    //no->setYawPitchRoll(orxonox::Degree(-90),orxonox::Degree(-90),orxonox::Degree(0));
+    no->setMesh("assff.mesh");
+    no->setMaxSpeed(500);
+    no->setMaxSideAndBackSpeed(50);
+    no->setMaxRotation(1.0);
+    no->setTransAcc(200);
+    no->setRotAcc(3.0);
+    no->setTransDamp(75);
+    no->setRotDamp(1.0);
+    no->setCamera("cam_"+client->getID());
+    no->classID = id->getNetworkID();
+    no->create();
+    
+    client->setShipID(no->objectID);
+    return true;
+  }
+  
+  bool Server::disconnectClient(ENetEvent *event){
+    COUT(4) << "removing client from list" << std::endl;
+    //return removeClient(head_->findClient(&(peer->address))->getID());
+    
+    //boost::recursive_mutex::scoped_lock lock(head_->mutex_);
+    orxonox::Iterator<orxonox::SpaceShip> it = orxonox::ObjectList<orxonox::SpaceShip>::start();
+    ClientInformation *client = clients->findClient(&event->peer->address);
+    if(!client)
+      return false;
+    while(it){
+      if(it->objectID!=client->getShipID()){
+        ++it;
+        continue;
+      }
+      orxonox::Iterator<orxonox::SpaceShip> temp=it;
+      ++it;
+      delete  *temp;
+      return clients->removeClient(event->peer);
+    }
+    return false;
   }
 
Index: code/trunk/src/network/Server.h
===================================================================
--- code/trunk/src/network/Server.h	(revision 1407)
+++ code/trunk/src/network/Server.h	(revision 1502)
@@ -60,4 +60,5 @@
   public:
     Server();
+    Server(int port);
     Server(int port, std::string bindAddress);
     Server(int port, const char *bindAddress);
@@ -71,4 +72,8 @@
     void updateGamestate();
   private:
+    bool addClient(ENetEvent *event);
+    bool createClient(int clientID);
+    bool createShip(ClientInformation *client);
+    bool disconnectClient(ENetEvent *event);
     void disconnectClient(int clientID);
     void disconnectClient( ClientInformation *client);
@@ -82,4 +87,5 @@
 
     ClientInformation *clients;
+    float timeSinceLastUpdate_;
   };
 
Index: code/trunk/src/network/Synchronisable.cc
===================================================================
--- code/trunk/src/network/Synchronisable.cc	(revision 1407)
+++ code/trunk/src/network/Synchronisable.cc	(revision 1502)
@@ -66,4 +66,10 @@
 
   Synchronisable::~Synchronisable(){
+  }
+  
+  bool Synchronisable::create(){
+    this->classID = this->getIdentifier()->getNetworkID();
+    COUT(4) << "creating synchronisable: setting classid from " << this->getIdentifier()->getName() << " to: " << classID << std::endl;
+    return true;
   }
   
@@ -151,6 +157,8 @@
   * @return data containing all variables and their sizes
   */
-  syncData Synchronisable::getData(unsigned char *mem){
+  syncData Synchronisable::getData(unsigned char *mem, int mode){
     //std::cout << "inside getData" << std::endl;
+    if(mode==0x0)
+      mode=state_;
     if(classID==0)
       COUT(3) << "classid 0 " << this->getIdentifier()->getName() << std::endl;
@@ -167,5 +175,5 @@
     for(i=syncList->begin(); n<datasize && i!=syncList->end(); ++i){
       //(std::memcpy(retVal.data+n, (const void*)(&(i->size)), sizeof(int));
-      if( ((*i)->mode & state_) == 0 ){
+      if( ((*i)->mode & mode) == 0 ){
         COUT(5) << "not getting data: " << std::endl;
         continue;  // this variable should only be received
@@ -194,5 +202,7 @@
   * @return true/false
   */
-  bool Synchronisable::updateData(syncData vars){
+  bool Synchronisable::updateData(syncData vars, int mode){
+    if(mode==0x0)
+      mode=state_;
     unsigned char *data=vars.data;
     std::list<synchronisableVariable *>::iterator i;
@@ -203,7 +213,7 @@
     COUT(5) << "Synchronisable: objectID " << vars.objectID << ", classID " << vars.classID << " size: " << vars.length << " synchronising data" << std::endl;
     for(i=syncList->begin(); i!=syncList->end(); i++){
-      if( ((*i)->mode ^ state_) == 0 ){
+      if( ((*i)->mode ^ mode) == 0 ){
         COUT(5) << "synchronisable: not updating variable " << std::endl;
-        continue;  // this variable should only be updated
+        continue;  // this variable should only be set
       }
       COUT(5) << "Synchronisable: element size: " << (*i)->size << " type: " << (*i)->type << std::endl;
@@ -230,9 +240,11 @@
   * @return amount of bytes
   */
-  int Synchronisable::getSize(){
+  int Synchronisable::getSize(int mode){
     int tsize=0;
+    if(mode==0x0)
+      mode=state_;
     std::list<synchronisableVariable *>::iterator i;
     for(i=syncList->begin(); i!=syncList->end(); i++){
-      if( ((*i)->mode & state_) == 0 )
+      if( ((*i)->mode & mode) == 0 )
         continue;  // this variable should only be received, so dont add its size to the send-size
       switch((*i)->type){
Index: code/trunk/src/network/Synchronisable.h
===================================================================
--- code/trunk/src/network/Synchronisable.h	(revision 1407)
+++ code/trunk/src/network/Synchronisable.h	(revision 1502)
@@ -83,11 +83,11 @@
     void registerVar(void *var, int size, variableType t, int mode=1);
     //  syncData getData();
-    syncData getData(unsigned char *mem);
-    int getSize();
-    bool updateData(syncData vars);
+    syncData getData(unsigned char *mem, int mode=0x0);
+    int getSize(int mode=0x0);
+    bool updateData(syncData vars, int mode=0x0);
     void setBacksync(bool sync);
     bool getBacksync();
     virtual void registerAllVariables()=0;
-    virtual bool create()=0;
+    virtual bool create();
     static void setClient(bool b);
   protected:
Index: code/trunk/src/network/diffTest.cc
===================================================================
--- code/trunk/src/network/diffTest.cc	(revision 1407)
+++ code/trunk/src/network/diffTest.cc	(revision 1502)
@@ -549,5 +549,5 @@
 
   std::cout << "test setGamestateID" << std::endl;
-  temp->setGamestateID( 8 );
+  temp->setGameStateID( 8 );
   printClientInformationBox( temp );
 
@@ -559,5 +559,5 @@
   newInfo->setSynched( true );
   newInfo->setPeer( NULL );
-  toool->setGamestateID( 199 );
+  toool->setGameStateID( 199 );
   toool->setID( numberOfClients+1);
   toool->setSynched( true );
Index: code/trunk/src/network/dummyclient3.cc
===================================================================
--- code/trunk/src/network/dummyclient3.cc	(revision 1407)
+++ code/trunk/src/network/dummyclient3.cc	(revision 1502)
@@ -51,6 +51,11 @@
   Client client( str, PORT );
   if ( client.establishConnection() )
+  {
     COUT(3) << "connection established" << std::endl;
-  else COUT(0) << "problems establishing connection" << std::endl;
+  }
+  else
+  {
+    COUT(0) << "problems establishing connection" << std::endl;
+  }
   char message[10000];
   char signs[] = "abcdefghijklmnopqrstuvwxy";
Index: code/trunk/src/ois/CMakeLists.txt
===================================================================
--- code/trunk/src/ois/CMakeLists.txt	(revision 1407)
+++ code/trunk/src/ois/CMakeLists.txt	(revision 1502)
@@ -37,2 +37,11 @@
 
 ADD_LIBRARY( ois SHARED ${OIS_SRC_FILES} )
+
+IF(WIN32)
+  LINK_DIRECTORIES(${DirectX_LIB_DIR})
+  TARGET_LINK_LIBRARIES( ois
+    dxguid
+    dinput8
+  )
+ENDIF(WIN32)
+
Index: code/trunk/src/ois/OISException.cpp
===================================================================
--- code/trunk/src/ois/OISException.cpp	(revision 1407)
+++ code/trunk/src/ois/OISException.cpp	(revision 1502)
@@ -26,7 +26,7 @@
 
 //----------------------------------------------------------------------------//
-const char* Exception::what() const throw()
+/*const char* Exception::what() const throw()
 {
 	return eText;
 }
-
+*/
Index: code/trunk/src/ois/OISException.h
===================================================================
--- code/trunk/src/ois/OISException.h	(revision 1407)
+++ code/trunk/src/ois/OISException.h	(revision 1502)
@@ -58,7 +58,6 @@
 			: eType(err), eLine(line), eFile(file), eText(str) {}
 
-		~Exception() throw() {}
-
-		virtual const char* what() const throw();
+		virtual const char* what() const throw()
+            { return eText; }
 
 		//! The type of exception raised
Index: code/trunk/src/orxonox/CMakeLists.txt
===================================================================
--- code/trunk/src/orxonox/CMakeLists.txt	(revision 1407)
+++ code/trunk/src/orxonox/CMakeLists.txt	(revision 1502)
@@ -9,4 +9,5 @@
   hud/RadarOverlayElement.cc
   hud/RadarObject.cc
+  hud/Navigation.cc
   particle/ParticleInterface.cc
   tolua/tolua_bind.cc
@@ -24,6 +25,8 @@
   objects/NPC.cc
   objects/Projectile.cc
+  objects/RotatingProjectile.cc
   objects/Skybox.cc
   objects/SpaceShip.cc
+  objects/SpaceShipAI.cc
   objects/WorldEntity.cc
 
Index: code/trunk/src/orxonox/GraphicsEngine.cc
===================================================================
--- code/trunk/src/orxonox/GraphicsEngine.cc	(revision 1407)
+++ code/trunk/src/orxonox/GraphicsEngine.cc	(revision 1502)
@@ -45,8 +45,13 @@
 #include "core/Debug.h"
 #include "core/CommandExecutor.h"
-
+#include "core/TclBind.h"
+#include "console/InGameConsole.h"
+
+#include "core/ConsoleCommand.h"
+#include <OgreSceneManager.h>
+#include <OgreCompositorManager.h>
+#include <OgreViewport.h>
 
 namespace orxonox {
-
   /**
     @brief Returns the singleton instance and creates it the first time.
@@ -83,4 +88,6 @@
     SetConfigValue(ogreLogLevelNormal_  , 4).description("Corresponding orxonox debug level for ogre Normal");
     SetConfigValue(ogreLogLevelCritical_, 2).description("Corresponding orxonox debug level for ogre Critical");
+
+    TclBind::getInstance().setDataPath(this->dataPath_);
   }
 
@@ -137,5 +144,7 @@
 #endif
 
-/*    // create a logManager
+// TODO: LogManager doesn't work on specific systems. The why is unknown yet.
+#if ORXONOX_PLATFORM == ORXONOX_PLATFORM_WIN32
+    // create a logManager
     // note: If there's already a logManager, Ogre will complain by a failed assertation.
     // but that shouldn't happen, since this is the first time to create a logManager..
@@ -148,13 +157,24 @@
       myLog = logger->createLog("ogre.log", true, false, true);
     else
-          myLog = logger->createLog(this->ogreLogfile_, true, false, false);
+      myLog = logger->createLog(this->ogreLogfile_, true, false, false);
     CCOUT(4) << "Ogre Log created" << std::endl;
 
     myLog->setLogDetail(Ogre::LL_BOREME);
-    myLog->addListener(this);*/
+    myLog->addListener(this);
+#endif
 
     // Root will detect that we've already created a Log
     CCOUT(4) << "Creating Ogre Root..." << std::endl;
-    root_ = new Ogre::Root(plugin_filename);
+
+    root_ = new Ogre::Root(plugin_filename, "ogre.cfg", this->ogreLogfile_);
+
+#if ORXONOX_PLATFORM != ORXONOX_PLATFORM_WIN32
+    // tame the ogre ouput so we don't get all the mess in the console
+    Ogre::Log* defaultLog = Ogre::LogManager::getSingleton().getDefaultLog();
+    defaultLog->setDebugOutputEnabled(false);
+    defaultLog->setLogDetail(Ogre::LL_BOREME);
+    defaultLog->addListener(this);
+#endif
+
     CCOUT(4) << "Creating Ogre Root done" << std::endl;
 
@@ -241,5 +261,5 @@
   bool GraphicsEngine::createNewScene()
   {
-    CCOUT(4) << "Creating new SceneManager" << std::endl;
+    CCOUT(4) << "Creating new SceneManager..." << std::endl;
     if (scene_)
     {
@@ -291,4 +311,16 @@
     else
       return 0;
+  }
+
+  /**
+    @brief Returns the window aspect ratio height/width.
+    @return The ratio
+  */
+  float GraphicsEngine::getWindowAspectRatio() const
+  {
+    if (this->renderWindow_)
+        return (float)this->renderWindow_->getHeight() / (float)this->renderWindow_->getWidth();
+    else
+        return 1.0f;
   }
 
@@ -345,4 +377,5 @@
     int h = rw->getHeight();
     InputManager::setWindowExtents(w, h);
+    InGameConsole::getInstance().resize();
   }
 
@@ -365,3 +398,36 @@
     CommandExecutor::execute("exit", false);
   }
+
+  //HACK!!
+  /*SetConsoleCommandShortcut(GraphicsEngine, CompositorBloomOn).setAccessLevel(AccessLevel::User);
+  SetConsoleCommandShortcut(GraphicsEngine, CompositorMotionBlurOn).setAccessLevel(AccessLevel::User);
+  SetConsoleCommandShortcut(GraphicsEngine, CompositorBloomOff).setAccessLevel(AccessLevel::User);
+  SetConsoleCommandShortcut(GraphicsEngine, CompositorMotionBlurOff).setAccessLevel(AccessLevel::User);
+  void GraphicsEngine::CompositorBloomOn()
+  {
+    Ogre::SceneManager* mSceneMgr = GraphicsEngine::getSingleton().getSceneManager();
+    Ogre::Viewport* mViewport = mSceneMgr->getCurrentViewport();
+    Ogre::CompositorManager::getSingleton().addCompositor(mViewport, "Bloom");
+    Ogre::CompositorManager::getSingleton().setCompositorEnabled(mViewport, "Bloom", true);
+  }
+  void GraphicsEngine::CompositorBloomOff()
+  {
+    Ogre::SceneManager* mSceneMgr = GraphicsEngine::getSingleton().getSceneManager();
+    Ogre::Viewport* mViewport = mSceneMgr->getCurrentViewport();
+    Ogre::CompositorManager::getSingleton().setCompositorEnabled(mViewport, "Bloom", false);
+  }
+
+  void GraphicsEngine::CompositorMotionBlurOn()
+  {
+    Ogre::SceneManager* mSceneMgr = GraphicsEngine::getSingleton().getSceneManager();
+    Ogre::Viewport* mViewport = mSceneMgr->getCurrentViewport();
+    Ogre::CompositorManager::getSingleton().addCompositor(mViewport, "MotionBlur");
+    Ogre::CompositorManager::getSingleton().setCompositorEnabled(mViewport, "MotionBlur", true);
+  }
+  void GraphicsEngine::CompositorMotionBlurOff()
+  {
+    Ogre::SceneManager* mSceneMgr = GraphicsEngine::getSingleton().getSceneManager();
+    Ogre::Viewport* mViewport = mSceneMgr->getCurrentViewport();
+    Ogre::CompositorManager::getSingleton().setCompositorEnabled(mViewport, "MotionBlur", false);
+  }*/
 }
Index: code/trunk/src/orxonox/GraphicsEngine.h
===================================================================
--- code/trunk/src/orxonox/GraphicsEngine.h	(revision 1407)
+++ code/trunk/src/orxonox/GraphicsEngine.h	(revision 1502)
@@ -72,4 +72,7 @@
             int getWindowWidth() const;
             int getWindowHeight() const;
+            float getWindowAspectRatio() const;
+            float getAverageFPS() const
+            { if (renderWindow_) return this->renderWindow_->getAverageFPS(); else return 0.0f; }
 
             void windowMoved       (Ogre::RenderWindow* rw);
@@ -80,4 +83,11 @@
             static GraphicsEngine& getSingleton();
             static GraphicsEngine* getSingletonPtr() { return &getSingleton(); }
+
+            //HACK!!!
+            //void static CompositorBloomOn();
+            //void static CompositorBloomOff();
+            //void static CompositorMotionBlurOn();
+            //void static CompositorMotionBlurOff();
+
 
         private:
Index: code/trunk/src/orxonox/Main.cc
===================================================================
--- code/trunk/src/orxonox/Main.cc	(revision 1407)
+++ code/trunk/src/orxonox/Main.cc	(revision 1502)
@@ -36,5 +36,5 @@
 #include <exception>
 
-#include "OrxonoxPlatform.h"
+#include "util/OrxonoxPlatform.h"
 #include "core/SignalHandler.h"
 #include "Orxonox.h"
Index: code/trunk/src/orxonox/Orxonox.cc
===================================================================
--- code/trunk/src/orxonox/Orxonox.cc	(revision 1407)
+++ code/trunk/src/orxonox/Orxonox.cc	(revision 1502)
@@ -51,5 +51,4 @@
 //#include "util/Sleep.h"
 #include "util/ArgReader.h"
-#include "util/ExprParser.h"
 
 // core
@@ -57,8 +56,6 @@
 #include "core/ConsoleCommand.h"
 #include "core/Debug.h"
-#include "core/Factory.h"
 #include "core/Loader.h"
 #include "core/Tickable.h"
-#include "core/InputBuffer.h"
 #include "core/InputManager.h"
 #include "core/TclBind.h"
@@ -72,7 +69,8 @@
 
 // objects and tools
-#include "tools/Timer.h"
 #include "hud/HUD.h"
-#include "console/InGameConsole.h"
+#include <Ogre.h>
+
+#include "GraphicsEngine.h"
 
 // FIXME: is this really file scope?
@@ -83,71 +81,7 @@
 namespace orxonox
 {
-  ConsoleCommandShortcut(Orxonox, exit, AccessLevel::None).setKeybindMode(KeybindMode::OnPress);
-  ConsoleCommandShortcut(Orxonox, slomo, AccessLevel::Offline).setDefaultValue(0, 1.0)
-    .setAxisParamIndex(0).setIsAxisRelative(false);
-  ConsoleCommandShortcut(Orxonox, setTimeFactor, AccessLevel::Offline).setDefaultValue(0, 1.0);
-  ConsoleCommandShortcut(Orxonox, activateConsole, AccessLevel::None);
-  class Testconsole : public InputBufferListener
-  {
-    public:
-      Testconsole(InputBuffer* ib) : ib_(ib) {}
-      void listen() const
-      {
-        std::cout << "> " << this->ib_->get() << std::endl;
-      }
-      void execute() const
-      {
-        std::cout << ">> " << this->ib_->get() << std::endl;
-        if (!CommandExecutor::execute(this->ib_->get()))
-          std::cout << "Error" << std::endl;
-        this->ib_->clear();
-      }
-      void hintandcomplete() const
-      {
-        std::cout << CommandExecutor::hint(this->ib_->get()) << std::endl;
-        this->ib_->set(CommandExecutor::complete(this->ib_->get()));
-      }
-      void clear() const
-      {
-        this->ib_->clear();
-      }
-      void removeLast() const
-      {
-        this->ib_->removeLast();
-      }
-      void exit() const
-      {
-        InputManager::setInputState(InputManager::IS_NORMAL);
-      }
-
-    private:
-      InputBuffer* ib_;
-  };
-
-  class Calculator
-  {
-  public:
-    static float calculate(const std::string& calculation)
-    {
-      ExprParser expr(calculation);
-      if (expr.getSuccess())
-      {
-        if (expr.getResult() == 42.0)
-          std::cout << "Greetings from the restaurant at the end of the universe." << std::endl;
-        // FIXME: insert modifier to display in full precision
-        std::cout << "Result is: " << expr.getResult() << std::endl;
-        if (expr.getRemains() != "")
-          std::cout << "Warning: Expression could not be parsed to the end! Remains: '"
-              << expr.getRemains() << "'" << std::endl;
-        return expr.getResult();
-      }
-      else
-      {
-        std::cout << "Cannot calculate expression: Parse error" << std::endl;
-        return 0;
-      }
-    }
-  };
-  ConsoleCommandShortcut(Calculator, calculate, AccessLevel::None);
+  SetConsoleCommandShortcut(Orxonox, exit).setKeybindMode(KeybindMode::OnPress);
+  SetConsoleCommandShortcut(Orxonox, slomo).setAccessLevel(AccessLevel::Offline).setDefaultValue(0, 1.0).setAxisParamIndex(0).setIsAxisRelative(false);
+  SetConsoleCommandShortcut(Orxonox, setTimeFactor).setAccessLevel(AccessLevel::Offline).setDefaultValue(0, 1.0);
 
   /**
@@ -165,10 +99,10 @@
     // turn on frame smoothing by setting a value different from 0
     frameSmoothingTime_(0.0f),
-    orxonoxConsole_(0),
     orxonoxHUD_(0),
     bAbort_(false),
     timefactor_(1.0f),
     mode_(STANDALONE),
-    serverIp_("")
+    serverIp_(""),
+    serverPort_(NETWORK_PORT)
   {
   }
@@ -180,6 +114,6 @@
   {
     // keep in mind: the order of deletion is very important!
-    if (this->orxonoxHUD_)
-      delete this->orxonoxHUD_;
+//    if (this->orxonoxHUD_)
+//      delete this->orxonoxHUD_;
     Loader::close();
     InputManager::destroy();
@@ -244,4 +178,5 @@
     ar.checkArgument("data", dataPath, false);
     ar.checkArgument("ip", serverIp_, false);
+    ar.checkArgument("port", serverPort_, false);
     if(ar.errorHandling())
       return false;
@@ -251,4 +186,6 @@
     else if (mode == "server")
       mode_ = SERVER;
+    else if (mode == "dedicated")
+      mode_ = DEDICATED;
     else
     {
@@ -265,5 +202,4 @@
     // procedure until the GUI is identical
 
-    TclBind::getInstance().setDataPath(dataPath);
     ConfigFileManager::getSingleton()->setFile(CFT_Settings, "orxonox.ini");
     Factory::createClassHierarchy();
@@ -281,32 +217,38 @@
   bool Orxonox::start()
   {
-    //if (mode == DEDICATED)
-    // do something else
-    //else
-
-    if (!ogre_->loadRenderer())    // creates the render window
-      return false;
-
-    // Calls the InputManager which sets up the input devices.
-    // The render window width and height are used to set up the mouse movement.
-    if (!InputManager::initialise(ogre_->getWindowHandle(),
-          ogre_->getWindowWidth(), ogre_->getWindowHeight(), true, true, true))
-      return false;
-
-    // TODO: Spread this so that this call only initialises things needed for the GUI
-    if (!ogre_->initialiseResources())
-      return false;
-
-    // TOOD: load the GUI here
-    // set InputManager to GUI mode
-    InputManager::setInputState(InputManager::IS_GUI);
-    // TODO: run GUI here
-
-    // The following lines depend very much on the GUI output, so they're probably misplaced here..
-
-    InputManager::setInputState(InputManager::IS_NONE);
-
-    if (!loadPlayground())
-      return false;
+    if (mode_ == DEDICATED)
+    {
+      // do something else
+    }
+    else
+    { // not dedicated server
+      if (!ogre_->loadRenderer())    // creates the render window
+        return false;
+
+      // Calls the InputManager which sets up the input devices.
+      // The render window width and height are used to set up the mouse movement.
+      if (!InputManager::initialise(ogre_->getWindowHandle(),
+            ogre_->getWindowWidth(), ogre_->getWindowHeight(), true, true, true))
+        return false;
+
+      // TODO: Spread this so that this call only initialises things needed for the GUI
+      if (!ogre_->initialiseResources())
+        return false;
+
+      // TOOD: load the GUI here
+      // set InputManager to GUI mode
+      InputManager::setInputState(InputManager::IS_GUI);
+      // TODO: run GUI here
+
+      // The following lines depend very much on the GUI output, so they're probably misplaced here..
+
+      InputManager::setInputState(InputManager::IS_NONE);
+
+      // create Ogre SceneManager
+      ogre_->createNewScene();
+
+      if (!loadPlayground())
+        return false;
+    }
 
     switch (mode_)
@@ -320,4 +262,8 @@
         return false;
       break;
+    case DEDICATED:
+      if (!serverLoad())
+        return false;
+      break;
     default:
       if (!standaloneLoad())
@@ -336,7 +282,5 @@
   bool Orxonox::loadPlayground()
   {
-    ogre_->createNewScene();
-
-	  // Init audio
+    // Init audio
     //auMan_ = new audio::AudioManager();
     //auMan_->ambientAdd("a1");
@@ -348,25 +292,5 @@
     // Load the HUD
     COUT(3) << "Orxonox: Loading HUD..." << std::endl;
-    orxonoxHUD_ = new HUD(1);
-
-    COUT(3) << "Orxonox: Loading Console..." << std::endl;
-    InputBuffer* ib = dynamic_cast<InputBuffer*>(InputManager::getKeyHandler("buffer"));
-    /*
-    Testconsole* console = new Testconsole(ib);
-    ib->registerListener(console, &Testconsole::listen, true);
-    ib->registerListener(console, &Testconsole::execute, '\r', false);
-    ib->registerListener(console, &Testconsole::hintandcomplete, '\t', true);
-    ib->registerListener(console, &Testconsole::clear, '§', true);
-    ib->registerListener(console, &Testconsole::removeLast, '\b', true);
-    ib->registerListener(console, &Testconsole::exit, (char)0x1B, true);
-    */
-    orxonoxConsole_ = new InGameConsole(ib);
-    ib->registerListener(orxonoxConsole_, &InGameConsole::listen, true);
-    ib->registerListener(orxonoxConsole_, &InGameConsole::execute, '\r', false);
-    ib->registerListener(orxonoxConsole_, &InGameConsole::hintandcomplete, '\t', true);
-    ib->registerListener(orxonoxConsole_, &InGameConsole::clear, '§', true);
-    ib->registerListener(orxonoxConsole_, &InGameConsole::removeLast, '\b', true);
-    ib->registerListener(orxonoxConsole_, &InGameConsole::exit, (char)0x1B, true);
-
+    orxonoxHUD_ = &HUD::getSingleton();
     return true;
   }
@@ -379,5 +303,5 @@
     COUT(2) << "Loading level in server mode" << std::endl;
 
-    server_g = new network::Server();
+    server_g = new network::Server(serverPort_);
 
     if (!loadScene())
@@ -399,7 +323,9 @@
       client_g = network::Client::createSingleton();
     else
-      client_g = network::Client::createSingleton(serverIp_, NETWORK_PORT);
-
-    client_g->establishConnection();
+
+      client_g = network::Client::createSingleton(serverIp_, serverPort_);
+
+    if(!client_g->establishConnection())
+      return false;
     client_g->tick(0);
 
@@ -427,5 +353,15 @@
     Level* startlevel = new Level("levels/sample.oxw");
     Loader::open(startlevel);
-
+    
+    // HACK: shader stuff for presentation
+    /*Ogre::SceneManager* mSceneMgr = GraphicsEngine::getSingleton().getSceneManager();
+    mSceneMgr->setAmbientLight(ColourValue(0.4,0.4,0.4));
+    Ogre::Light* dirlight = mSceneMgr->createLight("Light1");
+
+    dirlight->setType(Ogre::Light::LT_DIRECTIONAL);
+    dirlight->setDirection(Vector3( 0, 1, 5 ));
+    dirlight->setDiffuseColour(ColourValue(0.6, 0.6, 0.4));
+    dirlight->setSpecularColour(ColourValue(1.0, 1.0, 1.0));*/
+    
     return true;
   }
@@ -453,11 +389,8 @@
     // Contains the times of recently fired events
     // eventTimes[4] is the list for the times required for the fps counter
-    std::deque<unsigned long> eventTimes[4];
+    std::deque<unsigned long> eventTimes[3];
     // Clear event times
-    for (int i = 0; i < 4; ++i)
+    for (int i = 0; i < 3; ++i)
       eventTimes[i].clear();
-    // fill the fps time list with zeros
-    for (int i = 0; i < 50; i++)
-      eventTimes[3].push_back(0);
 
     // use the ogre timer class to measure time.
@@ -466,15 +399,19 @@
     timer_->reset();
 
+    float renderTime = 0.0f;
+    float frameTime = 0.0f;
+    clock_t time = 0;
+
+    //Ogre::SceneManager* mSceneMgr = GraphicsEngine::getSingleton().getSceneManager();
+    //Ogre::Viewport* mViewport = mSceneMgr->getCurrentViewport();
+    
+    //Ogre::CompositorManager::getSingleton().addCompositor(mViewport, "Bloom");
+    //Ogre::CompositorManager::getSingleton().addCompositor(mViewport, "MotionBlur");
+
     COUT(3) << "Orxonox: Starting the main loop." << std::endl;
-	  while (!bAbort_)
-	  {
-		  // Pump messages in all registered RenderWindows
-      // This calls the WindowEventListener objects.
-      Ogre::WindowEventUtilities::messagePump();
-
+    while (!bAbort_)
+    {
       // get current time
       unsigned long now = timer_->getMilliseconds();
-      eventTimes[3].push_back(now);
-      eventTimes[3].erase(eventTimes[3].begin());
 
       // create an event to pass to the frameStarted method in ogre
@@ -482,18 +419,21 @@
       evt.timeSinceLastEvent = calculateEventTime(now, eventTimes[0]);
       evt.timeSinceLastFrame = calculateEventTime(now, eventTimes[1]);
+      frameTime += evt.timeSinceLastFrame;
 
       // show the current time in the HUD
-//      orxonoxHUD_->setTime((int)now, 0);
-//      orxonoxHUD_->setRocket2(ogreRoot.getCurrentFrameNumber());
-      if (eventTimes[3].back() - eventTimes[3].front() != 0)
-//        orxonoxHUD_->setRocket1((int)(50000.0f/(eventTimes[3].back() - eventTimes[3].front())));
-
-      // Iterate through all Tickables and call their tick(dt) function
+      // HUD::getSingleton().setTime(now);
+      if (mode_ != DEDICATED && frameTime > 0.4f)
+      {
+        HUD::getSingleton().setRenderTimeRatio(renderTime / frameTime);
+        frameTime = 0.0f;
+        renderTime = 0.0f;
+      }
+
+      // Call those objects that need the real time
+      for (Iterator<TickableReal> it = ObjectList<TickableReal>::start(); it; ++it)
+        it->tick((float)evt.timeSinceLastFrame);
+      // Call the scene objects
       for (Iterator<Tickable> it = ObjectList<Tickable>::start(); it; ++it)
         it->tick((float)evt.timeSinceLastFrame * this->timefactor_);
-      // Iterate through all TickableReals and call their tick(dt) function
-      for (Iterator<TickableReal> it = ObjectList<TickableReal>::start(); it; ++it)
-        it->tick((float)evt.timeSinceLastFrame);
-      orxonoxConsole_->tick((float)evt.timeSinceLastFrame);
 
       // don't forget to call _fireFrameStarted in ogre to make sure
@@ -501,23 +441,35 @@
       ogreRoot._fireFrameStarted(evt);
 
-      // server still renders at the moment
-      //if (mode_ != SERVER)
-      ogreRoot._updateAllRenderTargets(); // only render in non-server mode
-
       // get current time
       now = timer_->getMilliseconds();
+      calculateEventTime(now, eventTimes[2]);
+
+      if (mode_ != DEDICATED)
+      {
+        // Pump messages in all registered RenderWindows
+        // This calls the WindowEventListener objects.
+        Ogre::WindowEventUtilities::messagePump();
+
+        // render
+        ogreRoot._updateAllRenderTargets();
+      }
+
+      // get current time
+      now = timer_->getMilliseconds();
 
       // create an event to pass to the frameEnded method in ogre
       evt.timeSinceLastEvent = calculateEventTime(now, eventTimes[0]);
-      evt.timeSinceLastFrame = calculateEventTime(now, eventTimes[2]);
+      renderTime += calculateEventTime(now, eventTimes[2]);
 
       // again, just to be sure ogre works fine
       ogreRoot._fireFrameEnded(evt);
-	  }
-
-    if(mode_==CLIENT)
+      //msleep(200);
+    }
+
+    if (mode_ == CLIENT)
       network::Client::getSingleton()->closeConnection();
-    else if(mode_==SERVER)
+    else if (mode_ == SERVER)
       server_g->close();
+
     return true;
   }
@@ -560,12 +512,3 @@
     return (float)(times.back() - times.front()) / ((times.size() - 1) * 1000);
   }
-
-  /**
-   * Static function that shows the console in game mode.
-   */
-  void Orxonox::activateConsole()
-  {
-    // currently, the console shows itself when feeded with input.
-    InputManager::setInputState(InputManager::IS_CONSOLE);
-  }
 }
Index: code/trunk/src/orxonox/Orxonox.h
===================================================================
--- code/trunk/src/orxonox/Orxonox.h	(revision 1407)
+++ code/trunk/src/orxonox/Orxonox.h	(revision 1502)
@@ -50,5 +50,6 @@
     SERVER,
     CLIENT,
-    STANDALONE
+    STANDALONE,
+    DEDICATED
   };
 
@@ -70,5 +71,4 @@
       static inline float getTimeFactor() { return Orxonox::getSingleton()->timefactor_; }
       static inline void exit() { Orxonox::getSingleton()->abortRequest(); }
-      static inline void activateConsole();
 
    private:
@@ -97,5 +97,4 @@
       // TODO: make this a config-value by creating a config class for orxonox
       float                 frameSmoothingTime_;
-      InGameConsole*        orxonoxConsole_;
       HUD*                  orxonoxHUD_;
       bool                  bAbort_;        //!< aborts the render loop if true
@@ -105,4 +104,5 @@
       gameMode              mode_;
       std::string           serverIp_;
+      int                   serverPort_;
 
       static Orxonox *singletonRef_s;
Index: code/trunk/src/orxonox/OrxonoxPlatform.h
===================================================================
--- code/trunk/src/orxonox/OrxonoxPlatform.h	(revision 1407)
+++ 	(revision )
@@ -1,274 +1,0 @@
-/*
- *   ORXONOX - the hottest 3D action shooter ever to exist
- *                    > www.orxonox.net <
- *
- *
- *   License notice:
- *
- *   This program is free software; you can redistribute it and/or
- *   modify it under the terms of the GNU General Public License
- *   as published by the Free Software Foundation; either version 2
- *   of the License, or (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   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:
- *      Reto Grieder
- *
- */
-
-/**
- @file
- @brief Various constants for compiler, architecture and platform. It's a mere
-        copy of the file found in the Ogre source code (OgrePlatform.h).
- */
-
-#ifndef _OrxonoxPlatform_H__
-#define _OrxonoxPlatform_H__
-
-namespace orxonox {
-/* Initial platform/compiler-related stuff to set.
-*/
-#define ORXONOX_PLATFORM_WIN32 1
-#define ORXONOX_PLATFORM_LINUX 2
-#define ORXONOX_PLATFORM_APPLE 3
-
-#define ORXONOX_COMPILER_MSVC 1
-#define ORXONOX_COMPILER_GNUC 2
-#define ORXONOX_COMPILER_BORL 3
-
-#define ORXONOX_ENDIAN_LITTLE 1
-#define ORXONOX_ENDIAN_BIG 2
-
-#define ORXONOX_ARCHITECTURE_32 1
-#define ORXONOX_ARCHITECTURE_64 2
-
-/* Finds the compiler type and version.
-*/
-#if defined( _MSC_VER )
-#  define ORXONOX_COMPILER ORXONOX_COMPILER_MSVC
-#  define ORXONOX_COMP_VER _MSC_VER
-
-#elif defined( __GNUC__ )
-#  define ORXONOX_COMPILER ORXONOX_COMPILER_GNUC
-#  define ORXONOX_COMP_VER (((__GNUC__)*100) + \
-        (__GNUC_MINOR__*10) + \
-        __GNUC_PATCHLEVEL__)
-
-#elif defined( __BORLANDC__ )
-#  define ORXONOX_COMPILER ORXONOX_COMPILER_BORL
-#  define ORXONOX_COMP_VER __BCPLUSPLUS__
-
-#else
-#  pragma error "No known compiler. Abort! Abort!"
-
-#endif
-
-/* See if we can use __forceinline or if we need to use __inline instead */
-#if ORXONOX_COMPILER == ORXONOX_COMPILER_MSVC
-#  if ORXONOX_COMP_VER >= 1200
-#    define FORCEINLINE __forceinline
-#  endif
-#elif defined(__MINGW32__)
-#  if !defined(FORCEINLINE)
-#    define FORCEINLINE __inline
-#  endif
-#else
-#  define FORCEINLINE __inline
-#endif
-
-/* Finds the current platform */
-
-#if defined( __WIN32__ ) || defined( _WIN32 )
-#  define ORXONOX_PLATFORM ORXONOX_PLATFORM_WIN32
-
-#elif defined( __APPLE_CC__)
-#  define ORXONOX_PLATFORM ORXONOX_PLATFORM_APPLE
-
-#else
-#  define ORXONOX_PLATFORM ORXONOX_PLATFORM_LINUX
-#endif
-
-    /* Find the arch type */
-#if defined(__x86_64__) || defined(_M_X64) || defined(__powerpc64__) || defined(__alpha__) || defined(__ia64__) || defined(__s390__) || defined(__s390x__)
-#  define ORXONOX_ARCH_TYPE ORXONOX_ARCHITECTURE_64
-#else
-#  define ORXONOX_ARCH_TYPE ORXONOX_ARCHITECTURE_32
-#endif
-
-// For generating compiler warnings - should work on any compiler
-// As a side note, if you start your message with 'Warning: ', the MSVC
-// IDE actually does catch a warning :)
-// FIXME: Try this on linux box. Doesn't work with msvc
-//#define ORXONOX_QUOTE_INPLACE(x) # x
-//#define ORXONOX_QUOTE(x) ORXONOX_QUOTE_INPLACE(x)
-//#define ORXONOX_WARN( x )  message( __FILE__ "(" QUOTE( __LINE__ ) ") : " x "\n" )
-
-//----------------------------------------------------------------------------
-// Windows Settings
-#if ORXONOX_PLATFORM == ORXONOX_PLATFORM_WIN32
-
-// Win32 compilers use _DEBUG for specifying debug builds.
-#  ifdef _DEBUG
-#    define ORXONOX_DEBUG_MODE 1
-#  else
-#    define ORXONOX_DEBUG_MODE 0
-#  endif
-
-// Disable unicode support on MingW at the moment, poorly supported in stdlibc++
-// STLPORT fixes this though so allow if found
-// MinGW C++ Toolkit supports unicode and sets the define __MINGW32_TOOLKIT_UNICODE__ in _mingw.h
-#  if defined( __MINGW32__ ) && !defined(_STLPORT_VERSION)
-#    include<_mingw.h>
-#    if defined(__MINGW32_TOOLBOX_UNICODE__)
-#      define ORXONOX_UNICODE_SUPPORT 1
-#    else
-#      define ORXONOX_UNICODE_SUPPORT 0
-#    endif
-#  else
-#    define ORXONOX_UNICODE_SUPPORT 1
-#  endif
-
-#endif /* Platform Win32 */
-//----------------------------------------------------------------------------
-
-//----------------------------------------------------------------------------
-// Linux/Apple Settings
-#if ORXONOX_PLATFORM == ORXONOX_PLATFORM_LINUX || ORXONOX_PLATFORM == ORXONOX_PLATFORM_APPLE
-
-
-// A quick define to overcome different names for the same function
-#  define stricmp strcasecmp
-
-// Unlike the Win32 compilers, Linux compilers seem to use DEBUG for when
-// specifying a debug build.
-// (??? this is wrong, on Linux debug builds aren't marked in any way unless
-// you mark it yourself any way you like it -- zap ???)
-#  ifdef DEBUG
-#    define ORXONOX_DEBUG_MODE 1
-#  else
-#    define ORXONOX_DEBUG_MODE 0
-#  endif
-
-/* FIXME: Check what this actually is and whether we need it or not
-#  if ORXONOX_PLATFORM == ORXONOX_PLATFORM_APPLE
-#    define ORXONOX_PLATFORM_LIB "OrxonoxPlatform.bundle"
-#  else
-// ORXONOX_PLATFORM_LINUX
-#    define ORXONOX_PLATFORM_LIB "libOrxonoxPlatform.so"
-#  endif
-*/
-
-// Always enable unicode support for the moment
-// Perhaps disable in old versions of gcc if necessary
-#  define ORXONOX_UNICODE_SUPPORT 1
-
-#endif /* Patform Linux/Apple */
-
-//For apple, we always have a custom config.h file
-#if ORXONOX_PLATFORM == ORXONOX_PLATFORM_APPLE
-#  include "config.h"
-#endif
-
-//----------------------------------------------------------------------------
-
-//----------------------------------------------------------------------------
-// Endian Settings
-// check for BIG_ENDIAN config flag, set ORXONOX_ENDIAN correctly
-#ifdef ORXONOX_CONFIG_BIG_ENDIAN
-#  define ORXONOX_ENDIAN ORXONOX_ENDIAN_BIG
-#else
-#  define ORXONOX_ENDIAN ORXONOX_ENDIAN_LITTLE
-#endif
-
-// Integer formats of fixed bit width
-// FIXME: consider 64 bit platforms!
-//typedef unsigned int uint32;
-//typedef unsigned short uint16;
-//typedef unsigned char uint8;
-// proper approach
-
-#ifdef ORXONOX_DOUBLE_PRECISION
-typedef double Real;
-#else
-typedef float Real;
-#endif
-
-
-#if ORXONOX_COMPILER == ORXONOX_COMPILER_MSVC
-// Turn off warnings generated by long std templates
-// This warns about truncation to 255 characters in debug/browse info
-//#   pragma warning (disable : 4786)
-
-// Turn off warnings generated by long std templates
-// This warns about truncation to 255 characters in debug/browse info
-//#   pragma warning (disable : 4503)
-
-// disable: conversion from 'double' to 'float', possible loss of data
-// disable: conversion from 'ogg_int64_t' to 'long', possible loss of data
-// This has been dealt with in base_properties of the solution since the
-// warning primarily occurs in library header files (which are mostly
-// included before OrxonoxPlatform.h is)
-//#   pragma warning (disable : 4244)
-
-// disable: "conversion from 'size_t' to 'unsigned int', possible loss of data
-//#   pragma warning (disable : 4267)
-
-// disable: "truncation from 'double' to 'float'
-//#   pragma warning (disable : 4305)
-
-// set to level 4: "<type> needs to have dll-interface to be used by clients'
-// Happens on STL member variables which are not public therefore is ok
-#   pragma warning (disable : 4251)
-
-// disable: 'MultiTypeString' : multiple assignment operators specified
-// Used in MultiType and works fine so far
-//#   pragma warning (disable : 4522)
-
-// disable: "non dll-interface class used as base for dll-interface class"
-// Happens when deriving from Singleton because bug in compiler ignores
-// template export
-//#   pragma warning (disable : 4275)
-
-// disable: "C++ Exception Specification ignored"
-// This is because MSVC 6 did not implement all the C++ exception
-// specifications in the ANSI C++ draft.
-//#   pragma warning( disable : 4290 )
-
-// disable: "no suitable definition provided for explicit template
-// instantiation request" Occurs in VC7 for no justifiable reason on all
-// #includes of Singleton
-//#   pragma warning( disable: 4661)
-
-// disable: deprecation warnings when using CRT calls in VC8
-// These show up on all C runtime lib code in VC8, disable since they clutter
-// the warnings with things we may not be able to do anything about (e.g.
-// generated code from nvparse etc). I doubt very much that these calls
-// will ever be actually removed from VC anyway, it would break too much code.
-//#	pragma warning( disable: 4996)
-
-// disable: "conditional expression constant", always occurs on
-// ORXONOX_MUTEX_CONDITIONAL when no threading enabled
-//#   pragma warning (disable : 201)
-
-
-// Define the english written operators like and, or, xor
-#include <iso646.h>
-
-#endif /* ORXONOX_COMPILER == ORXONOX_COMPILER_MSVC */
-
-// include visual leak detector to search for memory leaks
-//#include <vld.h>
-
-} /* namespace orxonox */
-
-#endif /* _OrxonoxPlatform_H__ */
Index: code/trunk/src/orxonox/OrxonoxPrereqs.h
===================================================================
--- code/trunk/src/orxonox/OrxonoxPrereqs.h	(revision 1407)
+++ code/trunk/src/orxonox/OrxonoxPrereqs.h	(revision 1502)
@@ -35,5 +35,5 @@
 #define _OrxonoxPrereqs_H__
 
-#include "OrxonoxPlatform.h"
+#include "util/OrxonoxPlatform.h"
 
 //-----------------------------------------------------------------------
@@ -74,4 +74,5 @@
   class Skybox;
   class SpaceShip;
+  class SpaceShipAI;
   class WorldEntity;
 
@@ -95,5 +96,10 @@
 
   // hud
+  class BarOverlayElement;
   class HUD;
+  class Navigation;
+  class RadarObject;
+  class RadarOverlayElement;
+
   //console
   class InGameConsole;
Index: code/trunk/src/orxonox/OrxonoxStableHeaders.h
===================================================================
--- code/trunk/src/orxonox/OrxonoxStableHeaders.h	(revision 1407)
+++ code/trunk/src/orxonox/OrxonoxStableHeaders.h	(revision 1502)
@@ -35,5 +35,5 @@
 #define _OrxonoxStableHeaders_H__
 
-#include "OrxonoxPlatform.h"
+#include "util/OrxonoxPlatform.h"
 
 #if ORXONOX_COMPILER == ORXONOX_COMPILER_MSVC
@@ -109,5 +109,4 @@
 #include "network/Synchronisable.h"
 
-#include "OrxonoxPlatform.h"
 #include "OrxonoxPrereqs.h"
 #include "tools/Timer.h"
Index: code/trunk/src/orxonox/console/InGameConsole.cc
===================================================================
--- code/trunk/src/orxonox/console/InGameConsole.cc	(revision 1407)
+++ code/trunk/src/orxonox/console/InGameConsole.cc	(revision 1502)
@@ -23,5 +23,5 @@
  *      Felix Schulthess
  *   Co-authors:
- *      ...
+ *      Fabian 'x3n' Landau
  *
  */
@@ -40,243 +40,513 @@
 #include "core/Debug.h"
 #include "core/CoreIncludes.h"
+#include "core/ConfigValueIncludes.h"
 #include "core/ConsoleCommand.h"
 #include "core/InputManager.h"
+#include "util/Math.h"
 #include "GraphicsEngine.h"
 
-#define LINES 20
+#define LINES 30
+#define CHAR_WIDTH1 7.78 //34 // fix this please - determine the char-width dynamically
+#define CHAR_WIDTH2 8.28 // fix this please - determine the char-width dynamically
+#define CHAR_WIDTH3 7.80 //78 // fix this please - determine the char-width dynamically
 
 namespace orxonox
 {
+    SetConsoleCommand(InGameConsole, openConsole, true);
+    SetConsoleCommand(InGameConsole, closeConsole, true);
+
     using namespace Ogre;
 
-    const float REL_WIDTH = 0.8;
-    const float REL_HEIGHT = 0.4;
-    const float BLINK = 0.25;
-
-    InGameConsole::InGameConsole(InputBuffer* ib) :
-        windowW(0), windowH(0),
-        scroll(0), scrollTimer(0.0f),
-        cursor(0.0f),
-        active(false),
-        ib_(ib),
-        om(0),
-        consoleOverlay(0),
-        consoleOverlayContainer(0),
-        consoleOverlayNoise(0),
-        consoleOverlayBorder(0),
-        consoleOverlayTextAreas(0)
-    {
-        //RegisterObject(InGameConsole);
-        init();
-    }
-
-    InGameConsole::~InGameConsole(void){
-        for(int i=0; i<LINES; i++) delete consoleOverlayTextAreas[i];
-        delete consoleOverlayTextAreas;
-    }
-
-    void InGameConsole::listen(){
-        if(!active) activate();
-        print(convert2UTF(this->ib_->get()));
-    }
-
-    void InGameConsole::execute(){	
-        newline();
-        if (!CommandExecutor::execute(this->ib_->get())){
-            print("Error");
-            newline();
-        }
-        this->ib_->clear();
-    }
-
-    void InGameConsole::hintandcomplete(){
-        print(CommandExecutor::hint(this->ib_->get()));
-        newline();
-        this->ib_->set(CommandExecutor::complete(this->ib_->get()));
-        print(convert2UTF(this->ib_->get()));
-    }
-
-    void InGameConsole::clear(){
-        this->ib_->clear();
-    }
-
-    void InGameConsole::removeLast(){
-        this->ib_->removeLast();
-    }
-
-    void InGameConsole::exit(){
-        clear();
-        deactivate();
-        InputManager::setInputState(InputManager::IS_NORMAL);
-    }
-
-    /**
-    @brief called once by constructor
-    */
-    void InGameConsole::init(){
+    float InGameConsole::REL_WIDTH = 0.8;
+    float InGameConsole::REL_HEIGHT = 0.4;
+    float InGameConsole::BLINK = 0.5;
+
+    /**
+        @brief Constructor: Creates and initializes the InGameConsole.
+    */
+    InGameConsole::InGameConsole() :
+        om_(0), consoleOverlay_(0), consoleOverlayContainer_(0),
+        consoleOverlayNoise_(0), consoleOverlayBorder_(0), consoleOverlayTextAreas_(0)
+    {
+        RegisterObject(InGameConsole);
+
+        this->active_ = false;
+        this->cursor_ = 0.0;
+        this->cursorSymbol_ = '|';
+        this->inputWindowStart_ = 0;
+        this->numLinesShifted_ = LINES - 1;
+
+        this->init();
+        this->setConfigValues();
+
+        Shell::getInstance().addOutputLevel(true);
+    }
+
+    /**
+        @brief Destructor: Destroys the TextAreas.
+    */
+    InGameConsole::~InGameConsole(void)
+    {
+        /*for (int i = 0; i < LINES; i++)
+            if (this->consoleOverlayTextAreas_[i])
+                om_->destroyOverlayElement(this->consoleOverlayTextAreas_[i]);
+
+        if (this->consoleOverlayTextAreas_)
+            delete[] this->consoleOverlayTextAreas_;*/
+    }
+
+    /**
+        @brief Returns a reference to the only existing instance of InGameConsole.
+    */
+    InGameConsole& InGameConsole::getInstance()
+    {
+        static InGameConsole instance;
+        return instance;
+    }
+
+    /**
+        @brief Sets the config values, describing the size of the console.
+    */
+    void InGameConsole::setConfigValues()
+    {
+        SetConfigValue(REL_WIDTH, 0.8);
+        SetConfigValue(REL_HEIGHT, 0.4);
+        SetConfigValue(BLINK, 0.5);
+    }
+
+    /**
+        @brief Called if all output-lines have to be redrawn.
+    */
+    void InGameConsole::linesChanged()
+    {
+        std::list<std::string>::const_iterator it = Shell::getInstance().getNewestLineIterator();
+        int max = 0;
+        for (int i = 1; i < LINES; ++i)
+        {
+            if (it != Shell::getInstance().getEndIterator())
+            {
+                ++it;
+                max = i;
+            }
+            else
+                break;
+        }
+
+        for (int i = LINES - 1; i > max; --i)
+            this->print("", i, true);
+
+        for (int i = max; i >= 1; --i)
+        {
+            --it;
+            this->print(*it, i, true);
+        }
+    }
+
+    /**
+        @brief Called if only the last output-line has changed.
+    */
+    void InGameConsole::onlyLastLineChanged()
+    {
+        if (LINES > 1)
+            this->print(*Shell::getInstance().getNewestLineIterator(), 1);
+    }
+
+    /**
+        @brief Called if a new output-line was added.
+    */
+    void InGameConsole::lineAdded()
+    {
+        this->numLinesShifted_ = 0;
+        this->shiftLines();
+        this->onlyLastLineChanged();
+    }
+
+    /**
+        @brief Called if the text in the input-line has changed.
+    */
+    void InGameConsole::inputChanged()
+    {
+        if (LINES > 0)
+            this->print(Shell::getInstance().getInput(), 0);
+
+        if (Shell::getInstance().getInput() == "" || Shell::getInstance().getInput().size() == 0)
+            this->inputWindowStart_ = 0;
+    }
+
+    /**
+        @brief Called if the position of the cursor in the input-line has changed.
+    */
+    void InGameConsole::cursorChanged()
+    {
+        /*std::string input = Shell::getInstance().getInput();
+        input.insert(Shell::getInstance().getCursorPosition(), 1, this->cursorSymbol_);
+        if (LINES > 0)
+            this->print(input, 0);*/
+        this->setCursorPosition(Shell::getInstance().getCursorPosition() - inputWindowStart_);
+    }
+
+    /**
+        @brief Called if the console gets closed.
+    */
+    void InGameConsole::exit()
+    {
+        this->deactivate();
+    }
+
+    /**
+        @brief Called once by constructor, initializes the InGameConsole.
+    */
+    void InGameConsole::init()
+    {
         // for the beginning, don't scroll
-        scroll = 0;
-        scrollTimer = 0;
-        cursor = 0;
+        this->scroll_ = 0;
+        this->scrollTimer_ = 0;
+        this->cursor_ = 0;
 
         // create overlay and elements
-        om = &Ogre::OverlayManager::getSingleton();
+        this->om_ = &Ogre::OverlayManager::getSingleton();
 
         // create a container
-        consoleOverlayContainer = static_cast<OverlayContainer*>(om->createOverlayElement("Panel", "container"));
-        consoleOverlayContainer->setMetricsMode(Ogre::GMM_RELATIVE);
-        consoleOverlayContainer->setPosition((1-REL_WIDTH)/2, 0);
-        consoleOverlayContainer->setDimensions(REL_WIDTH, REL_HEIGHT);
+        this->consoleOverlayContainer_ = static_cast<OverlayContainer*>(this->om_->createOverlayElement("Panel", "InGameConsoleContainer"));
+        this->consoleOverlayContainer_->setMetricsMode(Ogre::GMM_RELATIVE);
+        this->consoleOverlayContainer_->setPosition((1 - InGameConsole::REL_WIDTH) / 2, 0);
+        this->consoleOverlayContainer_->setDimensions(InGameConsole::REL_WIDTH, InGameConsole::REL_HEIGHT);
 
         // create BorderPanel
-        consoleOverlayBorder = static_cast<BorderPanelOverlayElement*>(om->createOverlayElement("BorderPanel", "borderPanel"));
-        consoleOverlayBorder->setMetricsMode(Ogre::GMM_PIXELS);
-        consoleOverlayBorder->setMaterialName("ConsoleCenter");
+        this->consoleOverlayBorder_ = static_cast<BorderPanelOverlayElement*>(this->om_->createOverlayElement("BorderPanel", "InGameConsoleBorderPanel"));
+        this->consoleOverlayBorder_->setMetricsMode(Ogre::GMM_PIXELS);
+        this->consoleOverlayBorder_->setMaterialName("ConsoleCenter");
         // set parameters for border
-        consoleOverlayBorder->setBorderSize(16, 16, 0, 16);
-        consoleOverlayBorder->setBorderMaterialName("ConsoleBorder");
-        consoleOverlayBorder->setLeftBorderUV(0.0, 0.49, 0.5, 0.51);
-        consoleOverlayBorder->setRightBorderUV(0.5, 0.49, 1.0, 0.5);
-        consoleOverlayBorder->setBottomBorderUV(0.49, 0.5, 0.51, 1.0);
-        consoleOverlayBorder->setBottomLeftBorderUV(0.0, 0.5, 0.5, 1.0);
-        consoleOverlayBorder->setBottomRightBorderUV(0.5, 0.5, 1.0, 1.0);
+        this->consoleOverlayBorder_->setBorderSize(16, 16, 0, 16);
+        this->consoleOverlayBorder_->setBorderMaterialName("ConsoleBorder");
+        this->consoleOverlayBorder_->setLeftBorderUV(0.0, 0.49, 0.5, 0.51);
+        this->consoleOverlayBorder_->setRightBorderUV(0.5, 0.49, 1.0, 0.5);
+        this->consoleOverlayBorder_->setBottomBorderUV(0.49, 0.5, 0.51, 1.0);
+        this->consoleOverlayBorder_->setBottomLeftBorderUV(0.0, 0.5, 0.5, 1.0);
+        this->consoleOverlayBorder_->setBottomRightBorderUV(0.5, 0.5, 1.0, 1.0);
 
         // create the text lines
-        consoleOverlayTextAreas = new TextAreaOverlayElement*[LINES];
-        for(int i = 0; i<LINES; i++){
-            consoleOverlayTextAreas[i] = static_cast<TextAreaOverlayElement*>(om->createOverlayElement("TextArea", "textArea"+Ogre::StringConverter::toString(i)));
-            consoleOverlayTextAreas[i]->setMetricsMode(Ogre::GMM_PIXELS);
-            consoleOverlayTextAreas[i]->setFontName("Console");
-            consoleOverlayTextAreas[i]->setCharHeight(20);
-            consoleOverlayTextAreas[i]->setParameter("colour_top", "0.21 0.69 0.21");
-            consoleOverlayTextAreas[i]->setLeft(8);
-            consoleOverlayTextAreas[i]->setCaption("");
+        this->consoleOverlayTextAreas_ = new TextAreaOverlayElement*[LINES];
+        for (int i = 0; i < LINES; i++)
+        {
+            this->consoleOverlayTextAreas_[i] = static_cast<TextAreaOverlayElement*>(this->om_->createOverlayElement("TextArea", "InGameConsoleTextArea" + Ogre::StringConverter::toString(i)));
+            this->consoleOverlayTextAreas_[i]->setMetricsMode(Ogre::GMM_PIXELS);
+            this->consoleOverlayTextAreas_[i]->setFontName("Console");
+            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("");
         }
 
         // create noise
-        consoleOverlayNoise = static_cast<PanelOverlayElement*>(om->createOverlayElement("Panel", "noise"));
-        consoleOverlayNoise->setMetricsMode(Ogre::GMM_PIXELS);
-        consoleOverlayNoise->setPosition(5,0);
-        consoleOverlayNoise->setMaterialName("ConsoleNoise");
-
-        consoleOverlay = om->create("Console");
-        consoleOverlay->add2D(consoleOverlayContainer);
-        consoleOverlayContainer->addChild(consoleOverlayBorder);
-//comment following line to disable noise
-        consoleOverlayContainer->addChild(consoleOverlayNoise);
-        for(int i = 0; i<LINES; i++) consoleOverlayContainer->addChild(consoleOverlayTextAreas[i]);
-        resize();
+        this->consoleOverlayNoise_ = static_cast<PanelOverlayElement*>(this->om_->createOverlayElement("Panel", "InGameConsoleNoise"));
+        this->consoleOverlayNoise_->setMetricsMode(Ogre::GMM_PIXELS);
+        this->consoleOverlayNoise_->setPosition(5,0);
+        this->consoleOverlayNoise_->setMaterialName("ConsoleNoise");
+
+        // create cursor
+        this->consoleOverlayCursor_ = static_cast<PanelOverlayElement*>(this->om_->createOverlayElement("Panel", "InGameConsoleCursor"));
+        this->consoleOverlayCursor_->setMetricsMode(Ogre::GMM_PIXELS);
+        this->consoleOverlayCursor_->setPosition(5,219);
+        this->consoleOverlayCursor_->setDimensions(1, 14);
+        this->consoleOverlayCursor_->setMaterialName("Orxonox/GreenDot");
+
+        this->consoleOverlay_ = this->om_->create("InGameConsoleConsole");
+        this->consoleOverlay_->add2D(this->consoleOverlayContainer_);
+        this->consoleOverlayContainer_->addChild(this->consoleOverlayBorder_);
+        this->consoleOverlayContainer_->addChild(this->consoleOverlayCursor_);
+        //comment following line to disable noise
+        this->consoleOverlayContainer_->addChild(this->consoleOverlayNoise_);
+        for (int i = 0; i < LINES; i++)
+            this->consoleOverlayContainer_->addChild(this->consoleOverlayTextAreas_[i]);
+
+        this->resize();
 
         // move overlay "above" the top edge of the screen
         // we take -1.2 because the border mkes the panel bigger
-        consoleOverlayContainer->setTop(-1.2*REL_HEIGHT);
+        this->consoleOverlayContainer_->setTop(-1.2 * InGameConsole::REL_HEIGHT);
         // show overlay
-        consoleOverlay->show();
-
-        COUT(3) << "Info: InGameConsole initialized" << std::endl;
-    }
-
-    /**
-    @brief used to control the actual scrolling and cursor
-    */
-    void InGameConsole::tick(float dt){
-        scrollTimer += dt;
-        if(scrollTimer >= 0.01){
-            float top = consoleOverlayContainer->getTop();
-            scrollTimer = 0;
-            if(scroll!=0){
+        this->consoleOverlay_->show();
+
+        COUT(4) << "Info: InGameConsole initialized" << std::endl;
+    }
+
+    /**
+        @brief Resizes the console elements. Call if window size changes.
+    */
+    void InGameConsole::resize()
+    {
+        this->windowW_ = GraphicsEngine::getSingleton().getWindowWidth();
+        this->windowH_ = GraphicsEngine::getSingleton().getWindowHeight();
+        this->consoleOverlayBorder_->setWidth((int) this->windowW_* InGameConsole::REL_WIDTH);
+        this->consoleOverlayBorder_->setHeight((int) this->windowH_ * InGameConsole::REL_HEIGHT);
+        this->consoleOverlayNoise_->setWidth((int) this->windowW_ * InGameConsole::REL_WIDTH - 10);
+        this->consoleOverlayNoise_->setHeight((int) this->windowH_ * InGameConsole::REL_HEIGHT - 5);
+
+        // now adjust the text lines...
+        this->desiredTextWidth_ = (int) (this->windowW_ * InGameConsole::REL_WIDTH) - 12;
+
+        if (LINES > 0)
+            this->maxCharsPerLine_ = max((unsigned int)10, (unsigned int) ((float)this->desiredTextWidth_ / CHAR_WIDTH3));
+        else
+            this->maxCharsPerLine_ = 10;
+
+        for (int i = 0; i < LINES; i++)
+        {
+            this->consoleOverlayTextAreas_[i]->setWidth(this->desiredTextWidth_);
+            this->consoleOverlayTextAreas_[i]->setTop((int) this->windowH_ * InGameConsole::REL_HEIGHT - 24 - 14*i);
+        }
+
+        this->linesChanged();
+    }
+
+    /**
+        @brief Used to control the actual scrolling and the cursor.
+    */
+    void InGameConsole::tick(float dt)
+    {
+        this->scrollTimer_ += dt;
+        if (this->scrollTimer_ >= 0.01)
+        {
+            float top = this->consoleOverlayContainer_->getTop();
+            float timePassed = scrollTimer_;
+            this->scrollTimer_ = 0;
+            if (this->scroll_ != 0)
+            {
                 // scroll
-                top = top + 0.02*scroll;
-                consoleOverlayContainer->setTop(top);
+                top = top + timePassed * this->scroll_;
+                this->consoleOverlayContainer_->setTop(top);
             }
-            if(top <= -1.2*REL_HEIGHT){
+            if (top <= -1.2 * InGameConsole::REL_HEIGHT)
+            {
                 // window has completely scrolled up
-                scroll = 0;
-                consoleOverlay->hide();
-                active = false;
+                this->scroll_ = 0;
+                this->consoleOverlay_->hide();
+                this->active_ = false;
+                Shell::getInstance().unregisterListener(this);
             }
-            if(top >= 0){
+            if (top >= 0)
+            {
                 // window has completely scrolled down
-                scroll = 0;
-                consoleOverlayContainer->setTop(0);
-                active = true;
+                this->scroll_ = 0;
+                this->consoleOverlayContainer_->setTop(0);
+                this->active_ = true;
             }
         }
 
-        cursor += dt;
-        if(cursor >= 2*BLINK) cursor = 0;
-        print(convert2UTF(this->ib_->get()));
-
-// this creates a flickering effect
-        consoleOverlayNoise->setTiling(1, rand()%5+1);
-    }
-
-    /**
-    @brief resizes the console elements. call if window size changes
-    */
-    void InGameConsole::resize(){
-        windowW = GraphicsEngine::getSingleton().getWindowWidth();
-        windowH = GraphicsEngine::getSingleton().getWindowHeight();
-        consoleOverlayBorder->setWidth((int) windowW*REL_WIDTH);
-        consoleOverlayBorder->setHeight((int) windowH*REL_HEIGHT);
-        consoleOverlayNoise->setWidth((int) windowW*REL_WIDTH - 10);
-        consoleOverlayNoise->setHeight((int) windowH*REL_HEIGHT - 5);
-        // now adjust the text lines...
-        for(int i = 0; i<LINES; i++){
-            consoleOverlayTextAreas[i]->setWidth(windowW*REL_WIDTH);
-            consoleOverlayTextAreas[i]->setTop((int)windowH*REL_HEIGHT - 24 - 16*i);
-        }
-    }
-
-    /**
-    @brief shows console
-    */
-    void InGameConsole::activate(){
-        consoleOverlay->show();
+        this->cursor_ += dt;
+        if (this->cursor_ >= InGameConsole::BLINK)
+        {
+            this->cursor_ = 0;
+            bShowCursor_ = !bShowCursor_;
+            if (bShowCursor_)
+              this->consoleOverlayCursor_->show();
+            else
+              this->consoleOverlayCursor_->hide();
+        }
+
+        /*if (this->cursor_ >= 2 * InGameConsole::BLINK)
+          this->cursor_ = 0;
+
+        if (this->cursor_ >= InGameConsole::BLINK && this->cursorSymbol_ == '|')
+        {
+            this->cursorSymbol_ = ' ';
+            this->cursorChanged();
+        }
+        else if (this->cursor_ < InGameConsole::BLINK && this->cursorSymbol_ == ' ')
+        {
+            this->cursorSymbol_ = '|';
+            this->cursorChanged();
+        }*/
+
+        // this creates a flickering effect
+        this->consoleOverlayNoise_->setTiling(1, rand() % 5 + 1);
+    }
+
+    /**
+        @brief Shows the InGameConsole.
+    */
+    void InGameConsole::activate()
+    {
+        InputManager::setInputState(InputManager::IS_CONSOLE);
+        Shell::getInstance().registerListener(this);
+        this->linesChanged();
+
+        this->consoleOverlay_->show();
         // just in case window size has changed...
-        resize();
+        this->resize();
         // scroll down
-        scroll = 1;
+        this->scroll_ = 1;
         // the rest is done by tick
     }
 
     /**
-    @brief hides console
-    */
-    void InGameConsole::deactivate(){
+    @brief Hides the InGameConsole.
+    */
+    void InGameConsole::deactivate()
+    {
         // scroll up
-        scroll = -1;
+        this->scroll_ = -1;
         // the rest is done by tick
-    }
-
-    /**
-    @brief prints string to bottom line
-    @param s string to be printed
-    */
-    void InGameConsole::print(Ogre::UTFString s){
-        if(cursor>BLINK) consoleOverlayTextAreas[0]->setCaption(">" + s);
-        else consoleOverlayTextAreas[0]->setCaption(">" + s + "_");
-    }
-
-    /**
-    @brief shifts all lines up and clears the bottom line
-    */
-    void InGameConsole::newline(){
-        Ogre::UTFString line;
-        for(int i = LINES-1; i>=1; i--){
-            line = consoleOverlayTextAreas[i-1]->getCaption();
-            // don't copy the cursor...
-            int l = line.length();
-            if(!line.empty() && line.substr(l-1) == "_") line.erase(l-1);
-            consoleOverlayTextAreas[i]->setCaption(line);
-        }
-        consoleOverlayTextAreas[0]->setCaption(">");
-    }
-
-    Ogre::UTFString InGameConsole::convert2UTF(std::string s){
+        InputManager::setInputState(InputManager::IS_NORMAL);
+    }
+
+    /**
+        @brief Activates the console.
+    */
+    void InGameConsole::openConsole()
+    {
+        InGameConsole::getInstance().activate();
+    }
+
+    /**
+        @brief Deactivates the console.
+    */
+    void InGameConsole::closeConsole()
+    {
+        InGameConsole::getInstance().deactivate();
+    }
+
+    /**
+        @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(int colourcode, int index)
+    {
+        if (colourcode == -1)
+        {
+            this->consoleOverlayTextAreas_[index]->setColourTop   (ColourValue(0.90, 0.90, 0.90, 1.00));
+            this->consoleOverlayTextAreas_[index]->setColourBottom(ColourValue(1.00, 1.00, 1.00, 1.00));
+        }
+        else if (colourcode == 1)
+        {
+            this->consoleOverlayTextAreas_[index]->setColourTop   (ColourValue(0.95, 0.25, 0.25, 1.00));
+            this->consoleOverlayTextAreas_[index]->setColourBottom(ColourValue(1.00, 0.50, 0.50, 1.00));
+        }
+        else if (colourcode == 2)
+        {
+            this->consoleOverlayTextAreas_[index]->setColourTop   (ColourValue(0.95, 0.50, 0.20, 1.00));
+            this->consoleOverlayTextAreas_[index]->setColourBottom(ColourValue(1.00, 0.70, 0.50, 1.00));
+        }
+        else if (colourcode == 3)
+        {
+            this->consoleOverlayTextAreas_[index]->setColourTop   (ColourValue(0.50, 0.50, 0.95, 1.00));
+            this->consoleOverlayTextAreas_[index]->setColourBottom(ColourValue(0.80, 0.80, 1.00, 1.00));
+        }
+        else if (colourcode == 4)
+        {
+            this->consoleOverlayTextAreas_[index]->setColourTop   (ColourValue(0.65, 0.48, 0.44, 1.00));
+            this->consoleOverlayTextAreas_[index]->setColourBottom(ColourValue(1.00, 0.90, 0.90, 1.00));
+        }
+        else if (colourcode == 5)
+        {
+            this->consoleOverlayTextAreas_[index]->setColourTop   (ColourValue(0.40, 0.20, 0.40, 1.00));
+            this->consoleOverlayTextAreas_[index]->setColourBottom(ColourValue(0.80, 0.60, 0.80, 1.00));
+        }
+        else
+        {
+            this->consoleOverlayTextAreas_[index]->setColourTop   (ColourValue(0.21, 0.69, 0.21, 1.00));
+            this->consoleOverlayTextAreas_[index]->setColourBottom(ColourValue(0.80, 1.00, 0.80, 1.00));
+        }
+    }
+
+    void InGameConsole::setCursorPosition(int pos)
+    {
+        static std::string char1 = "bdefgilpqtzCEGIJKNOPQT5[}äü";
+        static std::string char2 = "Z4";
+
+        if (pos > (int)maxCharsPerLine_)
+          pos = maxCharsPerLine_;
+        else if (pos < 0)
+          pos = 0;
+
+        float width = 0;
+        for (int i = 0; i < pos; ++i)
+        {
+            if (char1.find(displayedText_[i]) != std::string::npos)
+                width += CHAR_WIDTH1;
+            else if (char2.find(displayedText_[i]) != std::string::npos)
+                width += CHAR_WIDTH2;
+            else
+                width += CHAR_WIDTH3;
+        }
+        this->consoleOverlayCursor_->setPosition(width + 5, this->windowH_ * InGameConsole::REL_HEIGHT - 20);
+    }
+
+    /**
+        @brief Prints string to bottom line.
+        @param s String to be printed
+    */
+    void InGameConsole::print(const std::string& text, int index, bool alwaysShift)
+    {
+        char level = 0;
+        if (text.size() > 0)
+            level = text[0];
+
+        std::string output = text;
+
+        if (level >= -1 && level <= 5)
+            output.erase(0, 1);
+
+        if (LINES > index)
+        {
+            this->colourLine(level, index);
+
+            if (index > 0)
+            {
+                unsigned int linesUsed = 1;
+                while (output.size() > this->maxCharsPerLine_)
+                {
+                    ++linesUsed;
+                    this->consoleOverlayTextAreas_[index]->setCaption(convert2UTF(output.substr(0, this->maxCharsPerLine_)));
+                    output.erase(0, this->maxCharsPerLine_);
+                    output.insert(0, 1, ' ');
+                    if (linesUsed > numLinesShifted_ || alwaysShift)
+                        this->shiftLines();
+                    this->colourLine(level, index);
+                }
+                this->consoleOverlayTextAreas_[index]->setCaption(convert2UTF(output));
+                this->displayedText_ = output;
+                this->numLinesShifted_ = linesUsed;
+            }
+            else
+            {
+                if (output.size() > this->maxCharsPerLine_)
+                {
+                    if (Shell::getInstance().getInputBuffer().getCursorPosition() < this->inputWindowStart_)
+                        this->inputWindowStart_ = Shell::getInstance().getInputBuffer().getCursorPosition();
+                    else if (Shell::getInstance().getInputBuffer().getCursorPosition() >= (this->inputWindowStart_ + this->maxCharsPerLine_ - 1))
+                        this->inputWindowStart_ = Shell::getInstance().getInputBuffer().getCursorPosition() - this->maxCharsPerLine_ + 1;
+
+                    output = output.substr(this->inputWindowStart_, this->maxCharsPerLine_);
+                }
+                else
+                  this->inputWindowStart_ = 0;
+                this->displayedText_ = output;
+                this->consoleOverlayTextAreas_[index]->setCaption(convert2UTF(output));
+            }
+        }
+    }
+
+    /**
+        @brief Converts a string into an Ogre::UTFString.
+        @param s The string to convert
+        @return The converted string
+    */
+    Ogre::UTFString InGameConsole::convert2UTF(std::string s)
+    {
         Ogre::UTFString utf;
-        int i;
         Ogre::UTFString::code_point cp;
-        for (i=0; i<(int)s.size(); ++i){
+        for (unsigned int i = 0; i < s.size(); ++i)
+        {
           cp = s[i];
           cp &= 0xFF;
Index: code/trunk/src/orxonox/console/InGameConsole.h
===================================================================
--- code/trunk/src/orxonox/console/InGameConsole.h	(revision 1407)
+++ code/trunk/src/orxonox/console/InGameConsole.h	(revision 1502)
@@ -23,5 +23,5 @@
  *      Felix Schulthess
  *   Co-authors:
- *      ...
+ *      Fabian 'x3n' Landau
  *
  */
@@ -37,44 +37,67 @@
 
 #include "core/Tickable.h"
-#include "core/InputBuffer.h"
+#include "core/Shell.h"
 
 
 namespace orxonox
 {
-    class _OrxonoxExport InGameConsole : public InputBufferListener
+    class _OrxonoxExport InGameConsole : public TickableReal, public ShellListener
     {
         public:
-            InGameConsole(InputBuffer* ib);
-            ~InGameConsole();
-            void listen();
-            void execute();
-            void hintandcomplete();
-            void clear();
-            void removeLast();
-            void exit();
-            void init();
+            static InGameConsole& getInstance();
+
+            void setConfigValues();
             void tick(float dt);
+
             void activate();
             void deactivate();
+            void resize();
+
+            static void openConsole();
+            static void closeConsole();
 
         private:
-            void resize();
-            void print(Ogre::UTFString s);
-            void newline();
-            Ogre::UTFString convert2UTF(std::string s);
+            InGameConsole();
+            InGameConsole(const InGameConsole& other);
+            ~InGameConsole();
 
-            int windowW;
-            int windowH;
-            int scroll;
-            float scrollTimer;
-            float cursor;
-            bool active;
-            InputBuffer* ib_;
-            Ogre::OverlayManager* om;
-            Ogre::Overlay* consoleOverlay;
-            Ogre::OverlayContainer* consoleOverlayContainer;
-            Ogre::PanelOverlayElement* consoleOverlayNoise;
-            Ogre::BorderPanelOverlayElement* consoleOverlayBorder;
-            Ogre::TextAreaOverlayElement** consoleOverlayTextAreas;
+            virtual void linesChanged();
+            virtual void onlyLastLineChanged();
+            virtual void lineAdded();
+            virtual void inputChanged();
+            virtual void cursorChanged();
+            virtual void exit();
+
+            void init();
+            void shiftLines();
+            void colourLine(int colourcode, int index);
+            void setCursorPosition(int pos);
+            void print(const std::string& text, int index, bool alwaysShift = false);
+            static Ogre::UTFString convert2UTF(std::string s);
+
+            static float REL_WIDTH;
+            static float REL_HEIGHT;
+            static float BLINK;
+
+            int windowW_;
+            int windowH_;
+            int desiredTextWidth_;
+            unsigned int maxCharsPerLine_;
+            unsigned int numLinesShifted_;
+            int scroll_;
+            float scrollTimer_;
+            float cursor_;
+            unsigned int inputWindowStart_;
+            char cursorSymbol_;
+            bool active_;
+            bool bShowCursor_;
+            std::string displayedText_;
+            Ogre::OverlayManager* om_;
+            Ogre::Overlay* consoleOverlay_;
+            Ogre::OverlayContainer* consoleOverlayContainer_;
+            Ogre::PanelOverlayElement* consoleOverlayNoise_;
+            Ogre::PanelOverlayElement* consoleOverlayCursor_;
+            Ogre::BorderPanelOverlayElement* consoleOverlayBorder_;
+            Ogre::TextAreaOverlayElement** consoleOverlayTextAreas_;
     };
 }
Index: code/trunk/src/orxonox/hud/BarOverlayElement.cc
===================================================================
--- code/trunk/src/orxonox/hud/BarOverlayElement.cc	(revision 1407)
+++ code/trunk/src/orxonox/hud/BarOverlayElement.cc	(revision 1502)
@@ -1,40 +1,40 @@
 /*
-*   ORXONOX - the hottest 3D action shooter ever to exist
-*
-*
-*   License notice:
-*
-*   This program is free software; you can redistribute it and/or
-*   modify it under the terms of the GNU General Public License
-*   as published by the Free Software Foundation; either version 2
-*   of the License, or (at your option) any later version.
-*
-*   This program is distributed in the hope that it will be useful,
-*   but WITHOUT ANY WARRANTY; without even the implied warranty of
-*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-*   GNU General Public License for more details.
-*
-*   You should have received a copy of the GNU General Public License
-*   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
-*
-*/
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   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
+ *
+ */
 
+#include "OrxonoxStableHeaders.h"
+#include "BarOverlayElement.h"
 #include <OgreOverlayManager.h>
-#include <OgreOverlayElement.h>
-#include <OgrePanelOverlayElement.h>
 #include "GraphicsEngine.h"
-#include "BarOverlayElement.h"
 
 namespace orxonox
 {
-  using namespace Ogre;
+    using namespace Ogre;
 
-    BarOverlayElement::BarOverlayElement(const String& name):Ogre::PanelOverlayElement(name){
+    BarOverlayElement::BarOverlayElement(const String& name):PanelOverlayElement(name){
         name_ = name;
     }
@@ -42,8 +42,8 @@
     BarOverlayElement::~BarOverlayElement(){}
 
-    void BarOverlayElement::init(Real leftRel, Real topRel, Real dimRel, Ogre::OverlayContainer* container){
+    void BarOverlayElement::init(Real leftRel, Real topRel, Real dimRel, OverlayContainer* container){
         // init some values...
         container_ = container;
-        om = &Ogre::OverlayManager::getSingleton();
+        om = &OverlayManager::getSingleton();
         value_ = 0;
         color_ = 2;
@@ -53,10 +53,10 @@
         topRel_ = topRel;
         dimRel_ = dimRel;
-        
+
         // create background...
         background_ = static_cast<OverlayContainer*>(om->createOverlayElement("Panel", name_+"container"));
         background_->show();
         container_->addChild(background_);
-        background_->setMetricsMode(Ogre::GMM_PIXELS);
+        background_->setMetricsMode(GMM_PIXELS);
         background_->setMaterialName("Orxonox/BarBackground");
 
@@ -65,5 +65,5 @@
 
         show();
-        setMetricsMode(Ogre::GMM_PIXELS);
+        setMetricsMode(GMM_PIXELS);
         setMaterialName("Orxonox/Green");
         background_->addChild(this);
@@ -126,4 +126,2 @@
     }
 }
-
-
Index: code/trunk/src/orxonox/hud/BarOverlayElement.h
===================================================================
--- code/trunk/src/orxonox/hud/BarOverlayElement.h	(revision 1407)
+++ code/trunk/src/orxonox/hud/BarOverlayElement.h	(revision 1502)
@@ -1,41 +1,37 @@
 /*
-*   ORXONOX - the hottest 3D action shooter ever to exist
-*
-*
-*   License notice:
-*
-*   This program is free software; you can redistribute it and/or
-*   modify it under the terms of the GNU General Public License
-*   as published by the Free Software Foundation; either version 2
-*   of the License, or (at your option) any later version.
-*
-*   This program is distributed in the hope that it will be useful,
-*   but WITHOUT ANY WARRANTY; without even the implied warranty of
-*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-*   GNU General Public License for more details.
-*
-*   You should have received a copy of the GNU General Public License
-*   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
-*
-*/
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   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
+ *
+ */
 
+#ifndef _BarOverlayElement_H__
+#define _BarOverlayElement_H__
 
-#ifndef _BAR_H__
-#define _BAR_H__
-
-#include <OgreOverlayManager.h>
-#include <OgreOverlayElement.h>
-#include <OgrePanelOverlayElement.h>
+#include "OrxonoxPrereqs.h"
 
 #include <OgrePrerequisites.h>
-#include "../OrxonoxPrereqs.h"
-
-
+#include <OgrePanelOverlayElement.h>
 
 namespace orxonox
@@ -44,37 +40,35 @@
   {
     private:
-        bool autoColor_;                    // whether bar changes color automatically
-        float value_;                       // progress of bar
-        int color_;
-        int left_;
-        int top_;
-        int width_;
-        int height_;
-        int windowW_, windowH_;
-        Ogre::Real leftRel_;
-        Ogre::Real topRel_;
-        Ogre::Real dimRel_;
-        Ogre::OverlayManager* om;           // our overlay manager
-        Ogre::OverlayContainer* container_; // our parent container to attach to
-        Ogre::OverlayContainer* background_;
-        Ogre::String name_;
+      bool autoColor_;                    // whether bar changes color automatically
+      float value_;                       // progress of bar
+      int color_;
+      int left_;
+      int top_;
+      int width_;
+      int height_;
+      int windowW_, windowH_;
+      Ogre::Real leftRel_;
+      Ogre::Real topRel_;
+      Ogre::Real dimRel_;
+      Ogre::OverlayManager* om;           // our overlay manager
+      Ogre::OverlayContainer* container_; // our parent container to attach to
+      Ogre::OverlayContainer* background_;
+      Ogre::String name_;
 
     public:
-        bool left2Right;
-        static const int RED = 0;           // predefined colors
-        static const int YELLOW = 1;
-        static const int GREEN = 2;
+      bool left2Right;
+      static const int RED = 0;           // predefined colors
+      static const int YELLOW = 1;
+      static const int GREEN = 2;
 
-        BarOverlayElement(const Ogre::String& name);
-        virtual ~BarOverlayElement();
-        void init(Real leftRel, Real topRel, Real dimRel, Ogre::OverlayContainer* container);
-        void resize();
-        void setValue(float value);
-        void setColor(int color);
-        float getValue();
-        int getBarColor();
+      BarOverlayElement(const Ogre::String& name);
+      virtual ~BarOverlayElement();
+      void init(Real leftRel, Real topRel, Real dimRel, Ogre::OverlayContainer* container);
+      void resize();
+      void setValue(float value);
+      void setColor(int color);
+      float getValue();
+      int getBarColor();
     };
 }
-#endif
-
-
+#endif /* _BarOverlayElement_H__ */
Index: code/trunk/src/orxonox/hud/HUD.cc
===================================================================
--- code/trunk/src/orxonox/hud/HUD.cc	(revision 1407)
+++ code/trunk/src/orxonox/hud/HUD.cc	(revision 1502)
@@ -1,52 +1,65 @@
 /*
-*   ORXONOX - the hottest 3D action shooter ever to exist
-*
-*
-*   License notice:
-*
-*   This program is free software; you can redistribute it and/or
-*   modify it under the terms of the GNU General Public License
-*   as published by the Free Software Foundation; either version 2
-*   of the License, or (at your option) any later version.
-*
-*   This program is distributed in the hope that it will be useful,
-*   but WITHOUT ANY WARRANTY; without even the implied warranty of
-*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-*   GNU General Public License for more details.
-*
-*   You should have received a copy of the GNU General Public License
-*   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
-*
-*/
-
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   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
+ *
+ */
 
 #include "OrxonoxStableHeaders.h"
+#include "HUD.h"
+
+#include <string>
+#include <set>
 #include <OgreOverlay.h>
 #include <OgreOverlayContainer.h>
 #include <OgreOverlayManager.h>
-#include <OgreSceneNode.h>
-#include <OgreEntity.h>
 #include <OgreStringConverter.h>
+
 #include "core/Debug.h"
+#include "core/ConsoleCommand.h"
 #include "objects/SpaceShip.h"
-#include "HUD.h"
+#include "GraphicsEngine.h"
 #include "BarOverlayElement.h"
+#include "RadarObject.h"
 #include "RadarOverlayElement.h"
+#include "Navigation.h"
 #include "OverlayElementFactories.h"
 
 namespace orxonox
 {
+    SetConsoleCommandShortcut(HUD, cycleNavigationFocus).setAccessLevel(AccessLevel::User);
+    SetConsoleCommandShortcut(HUD, toggleFPS).setAccessLevel(AccessLevel::User);
+    SetConsoleCommandShortcut(HUD, toggleRenderTime).setAccessLevel(AccessLevel::User);
+
     using namespace Ogre;
 
-    HUD::HUD(int zoom){
+    HUD::HUD(){
         om = &Ogre::OverlayManager::getSingleton();
-
-		// create Factories
+        sm = GraphicsEngine::getSingleton().getSceneManager();
+        showFPS = true;
+        showRenderTime = true;
+
+        // create Factories
         BarOverlayElementFactory *barOverlayElementFactory = new BarOverlayElementFactory();
         om->addOverlayElementFactory(barOverlayElementFactory);
@@ -56,12 +69,24 @@
         orxonoxHUD = om->create("Orxonox/HUD");
         container = static_cast<Ogre::OverlayContainer*>(om->createOverlayElement("Panel", "Orxonox/HUD/container"));
-        // test
-        test = static_cast<TextAreaOverlayElement*>(om->createOverlayElement("TextArea", "test123"));
-        test->show();
-        test->setMetricsMode(Ogre::GMM_RELATIVE);
-        test->setDimensions(0.8, 0.8);
-        test->setPosition(0.02, 0.02);
-        test->setFontName("Console");
-        test->setCaption("init");
+
+        // creating text to display fps
+        fpsText = static_cast<TextAreaOverlayElement*>(om->createOverlayElement("TextArea", "fpsText"));
+        fpsText->show();
+        fpsText->setMetricsMode(Ogre::GMM_PIXELS);
+        fpsText->setDimensions(0.001, 0.001);
+        fpsText->setPosition(10, 10);
+        fpsText->setFontName("Console");
+        fpsText->setCharHeight(20);
+        fpsText->setCaption("init");
+
+        // creating text to display render time ratio
+        rTRText = static_cast<TextAreaOverlayElement*>(om->createOverlayElement("TextArea", "rTRText"));
+        rTRText->show();
+        rTRText->setMetricsMode(Ogre::GMM_PIXELS);
+        rTRText->setDimensions(0.001, 0.001);
+        rTRText->setPosition(10, 30);
+        rTRText->setFontName("Console");
+        rTRText->setCharHeight(20);
+        rTRText->setCaption("init");
 
         // create energy bar
@@ -75,5 +100,8 @@
         radar->show();
 
-		// set up screen-wide container
+        // create Navigation
+        nav = new Navigation(container);
+
+        // set up screen-wide container
         container->show();
 
@@ -85,25 +113,36 @@
         container->setHeight(1.0);
         container->setMetricsMode(Ogre::GMM_RELATIVE);
-        container->addChild(test);
+        container->addChild(fpsText);
+        container->addChild(rTRText);
+
         energyBar->init(0.01, 0.94, 0.4, container);
         energyBar->setValue(1);
+
         speedoBar->init(0.01, 0.90, 0.4, container);
+
         radar->init(0.5, 0.9, 0.2, container);
-        radar->addObject(Vector3(1500.0, 0.0, 100.0));
-        radar->addObject(Vector3(0.0, 4000.0, 0.0));
-        radar->addObject(Vector3(0.0, 0.0, 6800.0));
-        RadarOverlayElement::cycleFocus();
+        SceneNode* node;
+        node = sm->getRootSceneNode()->createChildSceneNode("tomato1", Vector3(2000.0, 0.0, 0.0));
+        addRadarObject(node);
+        node = sm->getRootSceneNode()->createChildSceneNode("tomato2", Vector3(0.0, 2000.0, 0.0));
+        addRadarObject(node);
+        node = sm->getRootSceneNode()->createChildSceneNode("tomato3", Vector3(0.0, 0.0, 2000.0));
+        addRadarObject(node);
+	node = sm->getRootSceneNode()->createChildSceneNode("station", Vector3(10000.0,16000.0,0.0));
+        addRadarObject(node, 3);
+    }
+
+    HUD::~HUD(){
+        //todo: clean up objects
     }
 
     void HUD::tick(float dt)
     {
-        int d = radar->getDist2Focus()/10;
-        if(d) test->setCaption("Distance: " + Ogre::StringConverter::toString(d));
-        else test->setCaption("");
-
         energyBar->resize();
 
-        float v = SpaceShip::instance_s->getVelocity().length();
-        float vmax = SpaceShip::instance_s->getMaxSpeed();
+        if(!SpaceShip::getLocalShip())
+          return;
+        float v = SpaceShip::getLocalShip()->getVelocity().length();
+        float vmax = SpaceShip::getLocalShip()->getMaxSpeed();
         speedoBar->setValue(v/vmax);
         speedoBar->resize();
@@ -111,7 +150,75 @@
         radar->resize();
         radar->update();
-    }
-
-    HUD::~HUD(void){
+
+        nav->update();
+
+        setFPS();
+    }
+
+    void HUD::setRenderTimeRatio(float ratio)
+    {
+        if(showRenderTime){
+            rTRText->setCaption("Render time ratio: " + Ogre::StringConverter::toString(ratio));
+        }
+        else{
+            rTRText->setCaption("");
+            return;
+        }
+    }
+
+    void HUD::setFPS(){
+        if(showFPS){
+            float fps = GraphicsEngine::getSingleton().getAverageFPS();
+            fpsText->setCaption("FPS: " + Ogre::StringConverter::toString(fps));
+        }
+        else{
+            fpsText->setCaption("");
+            return;
+        }
+    }
+
+    void HUD::addRadarObject(SceneNode* node, int colour){
+        RadarObject* obj = new RadarObject(container, node, colour);
+        roSet.insert(obj);
+//        // check if this is the first RadarObject to create
+//        if(firstRadarObject == NULL){
+//            firstRadarObject = new RadarObject(container, node, colour);
+//            lastRadarObject = firstRadarObject;
+//        }
+//        else{ // if not, append to list
+//            lastRadarObject->next = new RadarObject(container, node, colour);
+//            lastRadarObject = lastRadarObject->next;
+//        }
+    }
+
+    void HUD::removeRadarObject(Ogre::SceneNode* node){
+      COUT(3) << "blabla" << std::endl;
+        for(std::set<RadarObject*>::iterator it=roSet.begin(); it!=roSet.end(); it++){
+            if((*it)->getNode() == node) {
+                delete (*it);
+                roSet.erase(it);
+            }
+        }
+    }
+
+    /*static*/ HUD& HUD::getSingleton(){
+        static HUD theInstance;
+        return theInstance;
+    }
+
+    /*static*/ void HUD::setEnergy(float value){
+        HUD::getSingleton().energyBar->setValue(value);
+    }
+
+    /*static*/ void HUD::cycleNavigationFocus(){
+        HUD::getSingleton().nav->cycleFocus();
+    }
+
+    /*static*/ void HUD::toggleFPS(){
+        HUD::getSingleton().showFPS = !HUD::getSingleton().showFPS;
+    }
+
+    /*static*/ void HUD::toggleRenderTime(){
+        HUD::getSingleton().showRenderTime = !HUD::getSingleton().showRenderTime;
     }
 }
Index: code/trunk/src/orxonox/hud/HUD.h
===================================================================
--- code/trunk/src/orxonox/hud/HUD.h	(revision 1407)
+++ code/trunk/src/orxonox/hud/HUD.h	(revision 1502)
@@ -1,28 +1,29 @@
 /*
-*   ORXONOX - the hottest 3D action shooter ever to exist
-*
-*
-*   License notice:
-*
-*   This program is free software; you can redistribute it and/or
-*   modify it under the terms of the GNU General Public License
-*   as published by the Free Software Foundation; either version 2
-*   of the License, or (at your option) any later version.
-*
-*   This program is distributed in the hope that it will be useful,
-*   but WITHOUT ANY WARRANTY; without even the implied warranty of
-*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-*   GNU General Public License for more details.
-*
-*   You should have received a copy of the GNU General Public License
-*   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
-*
-*/
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   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
+ *
+ */
 
 
@@ -30,14 +31,11 @@
 #define _HUD_H__
 
-#include <string.h>
-#include <OgreOverlayElement.h>
+#include "OrxonoxPrereqs.h"
+
+#include <OgrePrerequisites.h>
 #include <OgreTextAreaOverlayElement.h>
-#include <OgrePrerequisites.h>
-
-#include "OrxonoxPrereqs.h"
+#include <OgreSceneNode.h>
 #include "core/Tickable.h"
-#include "BarOverlayElement.h"
-#include "RadarOverlayElement.h"
-
+#include "util/Math.h"
 
 namespace orxonox
@@ -45,20 +43,39 @@
     class _OrxonoxExport HUD : public Tickable
     {
-        private:
-            Ogre::OverlayManager* om;
-            Ogre::Overlay* orxonoxHUD;
-            Ogre::OverlayContainer* container;
-            Ogre::TextAreaOverlayElement* test;
-            BarOverlayElement* energyBar;
-            BarOverlayElement* speedoBar;
-            RadarOverlayElement* radar;
+      private:
+        HUD();
+        HUD(HUD& instance);
+        ~HUD();
+        Ogre::OverlayManager* om;
+        Ogre::SceneManager* sm;
+        Ogre::Overlay* orxonoxHUD;
+        Ogre::OverlayContainer* container;
+        Ogre::TextAreaOverlayElement* fpsText;
+        Ogre::TextAreaOverlayElement* rTRText;
+        BarOverlayElement* energyBar;
+        BarOverlayElement* speedoBar;
+        RadarOverlayElement* radar;
+        Navigation* nav;
 
-        public:
-            HUD(int zoom);
-            ~HUD();
-            virtual void tick(float);
+        bool showFPS;
+        bool showRenderTime;
 
+      public:
+        virtual void tick(float);
+        void addRadarObject(Ogre::SceneNode* node, int colour = 0);
+        void removeRadarObject(Ogre::SceneNode* node);
+        void setRenderTimeRatio(float ratio);
+        void setFPS();
+
+        std::set<RadarObject*> roSet;
+
+        static HUD* instance_s;
+        static HUD& getSingleton();
+        static void setEnergy(float value);
+        static void cycleNavigationFocus();
+        static void toggleFPS();
+        static void toggleRenderTime();
     };
 }
 
-#endif
+#endif /* _HUD_H__ */
Index: code/trunk/src/orxonox/hud/Navigation.cc
===================================================================
--- code/trunk/src/orxonox/hud/Navigation.cc	(revision 1502)
+++ code/trunk/src/orxonox/hud/Navigation.cc	(revision 1502)
@@ -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:
+ *      Felix Schulthess
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "OrxonoxStableHeaders.h"
+#include "Navigation.h"
+
+#include <OgreOverlayManager.h>
+#include <OgreStringConverter.h>
+
+#include "GraphicsEngine.h"
+// TODO: remove the SpaceShip and CameraHandler dependencies
+#include "objects/SpaceShip.h"
+#include "objects/CameraHandler.h"
+#include "RadarObject.h"
+#include "RadarOverlayElement.h"
+#include "HUD.h"
+#include "core/Debug.h"
+
+namespace orxonox
+{
+    using namespace Ogre;
+
+    Navigation::Navigation(OverlayContainer* container){
+        container_ = container;
+        focus_ = NULL;
+        init();
+    }
+
+    Navigation::Navigation(OverlayContainer* container, RadarObject* focus){
+        container_ = container;
+        focus_ = focus;
+        init();
+    }
+
+    void Navigation::init(){
+        om = &OverlayManager::getSingleton();
+        navCam_ = NULL;
+        // create nav text
+        navText_ = static_cast<TextAreaOverlayElement*>(om->createOverlayElement("TextArea", "navText"));
+        navText_->show();
+        navText_->setMetricsMode(Ogre::GMM_PIXELS);
+        navText_->setDimensions(0.001, 0.001);
+        navText_->setPosition(0.02, 0.02);
+        navText_->setFontName("Console");
+        navText_->setCharHeight(20);
+        navText_->setCaption("");
+        container_->addChild(navText_);
+
+
+        // create nav marker ...
+        navMarker_ = static_cast<PanelOverlayElement*>(om->createOverlayElement("Panel", "NavMarker"));
+        navMarker_->setMetricsMode(GMM_PIXELS);
+        navMarker_->hide();
+        navText_->hide();
+        container_->addChild(navMarker_);
+    }
+
+    void Navigation::update(){
+        if(focus_ == NULL) return;
+        navCamPos_ = SpaceShip::getLocalShip()->getPosition();
+        currentDir_ = SpaceShip::getLocalShip()->getDir();
+        currentOrth_ = SpaceShip::getLocalShip()->getOrth();
+
+        windowW_ = GraphicsEngine::getSingleton().getWindowWidth();
+        windowH_ = GraphicsEngine::getSingleton().getWindowHeight();
+        updateMarker();
+    }
+
+    void Navigation::updateMarker(){
+        // set text
+        int dist = (int) getDist2Focus()/100;
+        navText_->setCaption(Ogre::StringConverter::toString(dist));
+
+        if(navCam_ == NULL) navCam_ = SpaceShip::getLocalShip()->getCamera()->cam_;
+        Vector3 pos = focus_->getPosition();
+        // transform to screen coordinates
+        pos = navCam_->getProjectionMatrix()*navCam_->getViewMatrix()*pos;
+        float xPosRel = 0.5*pos.x+0.5;
+        float yPosRel = 1-(0.5*pos.y+0.5);
+        int xPos = (int) (xPosRel*windowW_);
+        int yPos = (int) (yPosRel*windowH_);
+        int xFromCenter = xPos-windowW_/2;
+        int yFromCenter = yPos-windowH_/2;
+        // is object in view?
+        float radius = RadarOverlayElement::calcRadius(navCamPos_, currentDir_, currentOrth_, focus_);
+        bool isRight = (currentDir_.crossProduct(currentOrth_)).dotProduct(focus_->getPosition() - navCamPos_)>0;
+        bool isAbove = currentOrth_.dotProduct(focus_->getPosition() - navCamPos_)>0;
+        bool outOfView = (xPosRel<0 || xPosRel>1 || yPosRel<0 || yPosRel>1);
+        // if object is behind us, it is out of view anyway:
+        if(!outOfView && radius>3.14/2) outOfView = true;
+
+        if(outOfView){
+            // object is not in view
+            navMarker_->setMaterialName("Orxonox/NavArrows");
+            navMarker_->setDimensions(16,16);
+            float phiUpperCorner = atan((float)(windowW_)/(float)(windowH_));
+            // from the angle we find out on which edge to draw the marker
+            // and which of the four arrows to take
+            float phiNav = atan((float) xFromCenter / (float) yFromCenter);
+
+            if(isAbove && isRight){
+                // top right quadrant
+                if(-phiNav<phiUpperCorner){
+                    //COUT(3) << "arrow up\n";
+                    navMarker_->setPosition(-tan(phiNav)*windowH_/2+windowW_/2, 0);
+                    navMarker_->setUV(0.5, 0.0, 1.0, 0.5);
+                    navText_->setLeft(navMarker_->getLeft()+navMarker_->getWidth());
+                    navText_->setTop(navMarker_->getHeight());
+                }
+                else {
+                    //COUT(3) << "arrow right\n";
+                    navMarker_->setPosition(windowW_-16, tan((3.14-2*phiNav)/2)*windowW_/2+windowH_/2);
+                    navMarker_->setUV(0.5, 0.5, 1.0, 1.0);
+                    navText_->setLeft(navMarker_->getLeft()-navMarker_->getWidth());
+                    navText_->setTop(navMarker_->getTop()+navMarker_->getHeight());
+                }
+            }
+            if(!isAbove && isRight){
+                // bottom right quadrant
+                if(phiNav<phiUpperCorner) {
+                    //COUT(3) << "arrow down\n";
+                    navMarker_->setPosition(tan(phiNav)*windowH_/2+windowW_/2, windowH_-16);
+                    navMarker_->setUV(0.0, 0.5, 0.5, 1.0);
+                    navText_->setLeft(navMarker_->getLeft()+navMarker_->getWidth());
+                    navText_->setTop(navMarker_->getTop()-navMarker_->getHeight());
+                }
+                else {
+                    //COUT(3) << "arrow right\n";
+                    navMarker_->setPosition(windowW_-16, tan((3.14-2*phiNav)/2)*windowW_/2+windowH_/2);
+                    navMarker_->setUV(0.5, 0.5, 1.0, 1.0);
+                    navText_->setLeft(navMarker_->getLeft()-navMarker_->getWidth());
+                    navText_->setTop(navMarker_->getTop()+navMarker_->getHeight());
+                }
+            }
+            if(isAbove && !isRight){
+                // top left quadrant
+                if(phiNav<phiUpperCorner){
+                    //COUT(3) << "arrow up\n";
+                    navMarker_->setPosition(-tan(phiNav)*windowH_/2+windowW_/2, 0);
+                    navMarker_->setUV(0.5, 0.0, 1.0, 0.5);
+                    navText_->setLeft(navMarker_->getLeft()+navMarker_->getWidth());
+                    navText_->setTop(navMarker_->getHeight());
+                }
+                else {
+                    //COUT(3) << "arrow left\n";
+                    navMarker_->setPosition(0, -tan((3.14-2*phiNav)/2)*windowW_/2+windowH_/2);
+                    navMarker_->setUV(0.0, 0.0, 0.5, 0.5);
+                    navText_->setLeft(navMarker_->getWidth());
+                    navText_->setTop(navMarker_->getTop()+navMarker_->getHeight());
+                }
+            }
+            if(!isAbove && !isRight){
+                // bottom left quadrant
+                if(phiNav>-phiUpperCorner) {
+                    //COUT(3) << "arrow down\n";
+                    navMarker_->setPosition(tan(phiNav)*windowH_/2+windowW_/2, windowH_-16);
+                    navMarker_->setUV(0.0, 0.5, 0.5, 1.0);
+                    navText_->setLeft(navMarker_->getLeft()+navMarker_->getWidth());
+                    navText_->setTop(navMarker_->getTop()-navMarker_->getHeight());
+                }
+                else {
+                    //COUT(3) << "arrow left\n";
+                    navMarker_->setPosition(0, -tan((3.14-2*phiNav)/2)*windowW_/2+windowH_/2);
+                    navMarker_->setUV(0.0, 0.0, 0.5, 0.5);
+                    navText_->setLeft(navMarker_->getWidth());
+                    navText_->setTop(navMarker_->getTop()+navMarker_->getHeight());
+                }
+            }
+        }
+        else{
+            // object is in view
+            navMarker_->setMaterialName("Orxonox/NavTDC");
+            navMarker_->setDimensions(24,24);
+            navMarker_->setUV(0.0, 0.0, 1.0, 1.0);
+            navMarker_->setPosition(xPos-navMarker_->getWidth()/2, yPos-navMarker_->getHeight()/2);
+            navText_->setPosition(xPos+navMarker_->getWidth()/2, yPos+navMarker_->getHeight()/2);
+        }
+    }
+
+    void Navigation::cycleFocus(){
+        if(focus_ == NULL){
+            it_ = HUD::getSingleton().roSet.begin();
+            focus_ = *it_;
+            ++it_;
+        }
+        else{
+            focus_->resetColour();
+            if(it_ != HUD::getSingleton().roSet.end()){
+                focus_ = *it_;
+                ++it_;
+            }
+            else focus_ = NULL;
+        }
+        if(focus_ == NULL){
+            navMarker_->hide();
+            navText_->hide();
+        }
+        else{
+            navMarker_->show();
+            navText_->show();
+            focus_->setColour(RadarObject::WHITE);
+        }
+    }
+
+    float Navigation::getDist2Focus(){
+        if(focus_ == NULL) return(0.0);
+        return((focus_->getPosition()-SpaceShip::getLocalShip()->getPosition()).length());
+    }
+}
Index: code/trunk/src/orxonox/hud/Navigation.h
===================================================================
--- code/trunk/src/orxonox/hud/Navigation.h	(revision 1502)
+++ code/trunk/src/orxonox/hud/Navigation.h	(revision 1502)
@@ -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:
+ *      Felix Schulthess
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _Navigation_H__
+#define _Navigation_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <OgrePrerequisites.h>
+#include <OgreTextAreaOverlayElement.h>
+#include <OgrePanelOverlayElement.h>
+#include "util/Math.h"
+
+namespace orxonox
+{
+
+    class _OrxonoxExport Navigation
+    {
+      private:
+        Ogre::OverlayManager* om;				            // our one and only overlay manager
+        Ogre::OverlayContainer* container_;
+        Ogre::PanelOverlayElement* navMarker_;      // the panel used to show the arrow
+        Ogre::TextAreaOverlayElement* navText_;     // displaying distance
+        Ogre::Camera* navCam_;
+        Vector3 navCamPos_;                         // position of ship
+        Vector3 currentDir_;
+        Vector3 currentOrth_;
+        std::set<RadarObject*>::iterator it_;
+        int windowW_, windowH_;
+        void init();
+        void updateMarker();
+
+      public:
+        Navigation(Ogre::OverlayContainer* container);
+        Navigation(Ogre::OverlayContainer* container, RadarObject* focus);
+        ~Navigation();
+        RadarObject* focus_;                        // next pointer of linked list
+
+        void update();
+        void cycleFocus();
+        float getDist2Focus();
+  };
+}
+
+#endif /* _Navigation_H__ */
Index: code/trunk/src/orxonox/hud/OverlayElementFactories.h
===================================================================
--- code/trunk/src/orxonox/hud/OverlayElementFactories.h	(revision 1407)
+++ code/trunk/src/orxonox/hud/OverlayElementFactories.h	(revision 1502)
@@ -1,41 +1,45 @@
 /*
-*   ORXONOX - the hottest 3D action shooter ever to exist
-*
-*
-*   License notice:
-*
-*   This program is free software; you can redistribute it and/or
-*   modify it under the terms of the GNU General Public License
-*   as published by the Free Software Foundation; either version 2
-*   of the License, or (at your option) any later version.
-*
-*   This program is distributed in the hope that it will be useful,
-*   but WITHOUT ANY WARRANTY; without even the implied warranty of
-*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-*   GNU General Public License for more details.
-*
-*   You should have received a copy of the GNU General Public License
-*   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
-*
-*/
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   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
+ *
+ */
 
-#ifndef _FACTORIES_H__
-#define _FACTORIES_H__
+#ifndef _OverlayElementFactories_H__
+#define _OverlayElementFactories_H__
 
+#include "OrxonoxPrereqs.h"
+
+#include <OgrePrerequisites.h>
 #include <OgreOverlayElement.h>
-#include <OgrePrerequisites.h>
 #include <OgreOverlayElementFactory.h>
 
 #include "BarOverlayElement.h"
+#include "RadarOverlayElement.h"
 
 namespace orxonox{
     class _OrxonoxExport BarOverlayElementFactory : public Ogre::OverlayElementFactory{
-        public:
+      public:
         Ogre::OverlayElement* createOverlayElement(const Ogre::String& instanceName){
             return new BarOverlayElement(instanceName);
@@ -48,5 +52,5 @@
 
     class _OrxonoxExport RadarOverlayElementFactory : public Ogre::OverlayElementFactory{
-        public:
+      public:
         Ogre::OverlayElement* createOverlayElement(const Ogre::String& instanceName){
             return new RadarOverlayElement(instanceName);
@@ -59,3 +63,3 @@
 }
 
-#endif
+#endif /* _OverlayElementFactories_H__ */
Index: code/trunk/src/orxonox/hud/RadarObject.cc
===================================================================
--- code/trunk/src/orxonox/hud/RadarObject.cc	(revision 1407)
+++ code/trunk/src/orxonox/hud/RadarObject.cc	(revision 1502)
@@ -1,30 +1,36 @@
 /*
-*   ORXONOX - the hottest 3D action shooter ever to exist
-*
-*
-*   License notice:
-*
-*   This program is free software; you can redistribute it and/or
-*   modify it under the terms of the GNU General Public License
-*   as published by the Free Software Foundation; either version 2
-*   of the License, or (at your option) any later version.
-*
-*   This program is distributed in the hope that it will be useful,
-*   but WITHOUT ANY WARRANTY; without even the implied warranty of
-*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-*   GNU General Public License for more details.
-*
-*   You should have received a copy of the GNU General Public License
-*   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:
-*      ...
-*
-*/
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   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:
+ *      ...
+ *
+ */
 
+#include "OrxonoxStableHeaders.h"
 #include "RadarObject.h"
+
+#include <OgreOverlayManager.h>
+#include <OgreStringConverter.h>
+#include "GraphicsEngine.h"
 
 namespace orxonox
@@ -32,27 +38,15 @@
     using namespace Ogre;
 
-	int RadarObject::count = 0;		// initialize static variable
+    int RadarObject::count = 0;		// initialize static variable
 
-	RadarObject::RadarObject(Ogre::OverlayContainer* container){
-		container_ = container;
-		pos_ = Vector3(0.0, 0.0, 0.0);
-		init();
-	}
-
-	RadarObject::RadarObject(Ogre::OverlayContainer* container, Vector3 pos){
-		container_ = container;
-		pos_ = pos;
-		init();
-	}
-
-	RadarObject::~RadarObject(){}
-
-	void RadarObject::init(){
-	    next = NULL;
-		om = &Ogre::OverlayManager::getSingleton();
-		panel_ = static_cast<PanelOverlayElement*>(om->createOverlayElement("Panel",
-			"Object"+Ogre::StringConverter::toString(count)));
-		panel_->setMaterialName("Orxonox/RedDot");
-		panel_->setDimensions(3,3);
+    RadarObject::RadarObject(OverlayContainer* container, SceneNode* node, int colour){
+        container_ = container;
+        node_ = node;
+        colour_ = colour;
+        om = &OverlayManager::getSingleton();
+        panel_ = static_cast<PanelOverlayElement*>(om->createOverlayElement("Panel",
+            "Object"+StringConverter::toString(count)));
+        setColour(colour_);
+        panel_->setDimensions(3,3);
         panel_->setMetricsMode(Ogre::GMM_PIXELS);
         panel_->show();
@@ -60,10 +54,32 @@
         count++;
         container_->addChild(panel_);
-	}
+    }
+
+    RadarObject::~RadarObject(){
+        delete panel_;
+    }
+
+    void RadarObject::setColour(int colour){
+        switch(colour){
+        case RED: panel_->setMaterialName("Orxonox/RedDot"); break;
+        case YELLOW: panel_->setMaterialName("Orxonox/YellowDot"); break;
+        case GREEN: panel_->setMaterialName("Orxonox/GreenDot"); break;
+        case BLUE: panel_->setMaterialName("Orxonox/BlueDot"); break;
+        case WHITE: panel_->setMaterialName("Orxonox/WhiteDot"); break;
+        default: panel_->setMaterialName("Orxonox/RedDot"); break;
+        }
+    }
+
+    void RadarObject::resetColour(){
+        setColour(colour_);
+    }
+
+    Vector3 RadarObject::getPosition(){
+        return node_->getPosition();
+    }
+
+    SceneNode* RadarObject::getNode(){
+        return node_;
+    }
 }
 
-/* my local clipboard...
-COUT(3) << "WWWWWWWWWWWWWWWWWWWWWWWWWWWW\n";
-COUT(3) << firstRadarObject_->radius_ << "  " << firstRadarObject_->phi_ << std::endl;
-COUT(3) << "WWWWWWWWWWWWWWWWWWWWWWWWWWWW\n";
-*/
Index: code/trunk/src/orxonox/hud/RadarObject.h
===================================================================
--- code/trunk/src/orxonox/hud/RadarObject.h	(revision 1407)
+++ code/trunk/src/orxonox/hud/RadarObject.h	(revision 1502)
@@ -1,41 +1,38 @@
 /*
-*   ORXONOX - the hottest 3D action shooter ever to exist
-*
-*
-*   License notice:
-*
-*   This program is free software; you can redistribute it and/or
-*   modify it under the terms of the GNU General Public License
-*   as published by the Free Software Foundation; either version 2
-*   of the License, or (at your option) any later version.
-*
-*   This program is distributed in the hope that it will be useful,
-*   but WITHOUT ANY WARRANTY; without even the implied warranty of
-*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-*   GNU General Public License for more details.
-*
-*   You should have received a copy of the GNU General Public License
-*   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:
-*      ...
-*
-*/
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   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:
+ *      ...
+ *
+ */
 
-#ifndef _RADAR2_H__
-#define _RADAR2_H__
+#ifndef _RadarObject_H__
+#define _RadarObject_H__
 
-#include <string.h>
 #include <OgrePrerequisites.h>
-#include <OgreOverlayManager.h>
-#include <OgreOverlayElement.h>
+#include <OgreSceneNode.h>
 #include <OgrePanelOverlayElement.h>
-#include <OgreStringConverter.h>
-
-#include <util/Math.h>
-#include "../OrxonoxPrereqs.h"
+#include "OrxonoxPrereqs.h"
+#include "util/Math.h"
 
 namespace orxonox
@@ -43,24 +40,30 @@
     class _OrxonoxExport RadarObject
     {
-    	private:
-    		Ogre::OverlayManager* om;				// our one and only overlay manager
-    		void init();
+      private:
+        Ogre::OverlayManager* om;				// our one and only overlay manager
+        Ogre::SceneNode* node_;					// node of object
+        int colour_;
 
-    	public:
-    		RadarObject(Ogre::OverlayContainer* container);
-    		RadarObject(Ogre::OverlayContainer* container, Vector3 pos);
-    		~RadarObject();
+      public:
+        RadarObject(Ogre::OverlayContainer* container, Ogre::SceneNode* node, int colour = 0);
+        ~RadarObject();
+        void setColour(int colour);
+        void resetColour();
+        Vector3 getPosition();
+        Ogre::SceneNode* getNode();
 
-            bool right_;
-            int index_;                             // index number of object
-    		Vector3 pos_;							// position in space
-			Ogre::Real radius_, phi_;				// position on radar
-			Ogre::OverlayContainer* container_;
-			Ogre::PanelOverlayElement* panel_;		// the panel used to show the dot
-			RadarObject* next;                      // next pointer of linked list
+        bool right_;
+        int index_;                             // index number of object
+        Ogre::OverlayContainer* container_;
+        Ogre::PanelOverlayElement* panel_;		// the panel used to show the dot
 
-    		static int count;
-	};
+        static int count;
+        static const int RED = 0;
+        static const int YELLOW = 1;
+        static const int GREEN = 2;
+        static const int BLUE = 3;
+        static const int WHITE = 99;            // used if object got nav focus
+  };
 }
 
-#endif
+#endif /* _RadarObject_H__ */
Index: code/trunk/src/orxonox/hud/RadarOverlayElement.cc
===================================================================
--- code/trunk/src/orxonox/hud/RadarOverlayElement.cc	(revision 1407)
+++ code/trunk/src/orxonox/hud/RadarOverlayElement.cc	(revision 1502)
@@ -1,41 +1,49 @@
 /*
-*   ORXONOX - the hottest 3D action shooter ever to exist
-*
-*
-*   License notice:
-*
-*   This program is free software; you can redistribute it and/or
-*   modify it under the terms of the GNU General Public License
-*   as published by the Free Software Foundation; either version 2
-*   of the License, or (at your option) any later version.
-*
-*   This program is distributed in the hope that it will be useful,
-*   but WITHOUT ANY WARRANTY; without even the implied warranty of
-*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-*   GNU General Public License for more details.
-*
-*   You should have received a copy of the GNU General Public License
-*   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:
-*      ...
-*
-*/
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   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
+ *
+ */
 
+#include "OrxonoxStableHeaders.h"
 #include "RadarOverlayElement.h"
+
+#include <string>
+#include <OgreOverlayManager.h>
+#include <OgreStringConverter.h>
+
+#include "GraphicsEngine.h"
+#include "core/Tickable.h"
+#include "core/ConsoleCommand.h"
+#include "objects/SpaceShip.h"
+#include "RadarObject.h"
+#include "HUD.h"
 
 namespace orxonox
 {
-    ConsoleCommandShortcut(RadarOverlayElement, cycleFocus, AccessLevel::User);
-
     using namespace Ogre;
 
-    RadarOverlayElement* RadarOverlayElement::instance_s = NULL;
-
-    RadarOverlayElement::RadarOverlayElement(const String& name):Ogre::PanelOverlayElement(name){
-        RadarOverlayElement::instance_s = this;
+    RadarOverlayElement::RadarOverlayElement(const String& name):PanelOverlayElement(name){
     }
 
@@ -43,33 +51,13 @@
     }
 
-    void RadarOverlayElement::init(Real leftRel, Real topRel, Real dimRel, Ogre::OverlayContainer* container){
+    void RadarOverlayElement::init(Real leftRel, Real topRel, Real dimRel, OverlayContainer* container){
         // some initial data
-		om = &Ogre::OverlayManager::getSingleton();
+        om = &OverlayManager::getSingleton();
         dimRel_ = dimRel;
         leftRel_ = leftRel;
         topRel_ = topRel;
         container_ = container;
-        firstRadarObject_ = NULL;
-        lastRadarObject_ = NULL;
-        focus_ = NULL;
 
-        // create nav marker ...
-        navMarker_ = static_cast<PanelOverlayElement*>(om->createOverlayElement("Panel", "NavMarker"));
-        navMarker_->setMetricsMode(Ogre::GMM_PIXELS);
-        navMarker_->setMaterialName("Orxonox/NavMarker");
-        navMarker_->setDimensions(16,16);
-        navMarker_->setPosition(0,386);
-        navMarker_->hide();
-        container_->addChild(navMarker_);
-
-        // these have to fit the data in the level
-        shipPos_ = Vector3(0.0, 0.0, 0.0);
-        initialDir_ = Vector3(1.0, 0.0, 0.0);
-        currentDir_ = initialDir_;
-        initialOrth_ = Vector3(0.0, 0.0, 1.0);
-        currentOrth_ = initialOrth_;
-        plane = Plane(currentDir_, shipPos_);
-
-        setMetricsMode(Ogre::GMM_PIXELS);
+        setMetricsMode(GMM_PIXELS);
         setMaterialName("Orxonox/Radar");
         resize();
@@ -90,143 +78,57 @@
 
     void RadarOverlayElement::update() {
-        shipPos_ = SpaceShip::instance_s->getPosition();
-        currentDir_ = SpaceShip::instance_s->getOrientation()*initialDir_; 		// according to beni....
-		currentOrth_ = SpaceShip::instance_s->getOrientation()*initialOrth_;
-        plane = Plane(currentDir_, shipPos_);
-
-        RadarObject* ro = firstRadarObject_;
+        shipPos_ = SpaceShip::getLocalShip()->getPosition();
+        currentDir_ = SpaceShip::getLocalShip()->getDir();
+        currentOrth_ = SpaceShip::getLocalShip()->getOrth();
         // iterate through all RadarObjects
-		while(ro != NULL){
-		    // calc position on radar...
-            ro->radius_ = calcRadius(ro);
-            ro->phi_ = calcPhi(ro);
-            ro->right_ = calcRight(ro);
+        for(std::set<RadarObject*>::iterator it=HUD::getSingleton().roSet.begin(); it!=HUD::getSingleton().roSet.end(); it++){
+        // calc position on radar...
+            float radius = calcRadius(shipPos_, currentDir_, currentOrth_, (*it));
+            float phi = calcPhi(shipPos_, currentDir_, currentOrth_, (*it));
+            bool right = calcRight(shipPos_, currentDir_, currentOrth_, (*it));
 
             // set size to fit distance...
-            float d = (ro->pos_-shipPos_).length();
-            if(d<4000) ro->panel_->setDimensions(4,4);
-            else if(d<8000) ro->panel_->setDimensions(3,3);
-            else if(d<16000) ro->panel_->setDimensions(2,2);
-            else ro->panel_->setDimensions(1,1);
+            float d = ((*it)->getPosition()-shipPos_).length();
+            if(d<10000) (*it)->panel_->setDimensions(4,4);
+            else if(d<20000) (*it)->panel_->setDimensions(3,3);
+            else (*it)->panel_->setDimensions(2,2);
 
-            if (ro->right_){
-                ro->panel_->setPosition(sin(ro->phi_)*ro->radius_/
-                    3.5*dim_/2+dim_/2+left_-2,-cos(ro->phi_)*ro->radius_/3.5*dim_/2+dim_/2+top_-2);
+            if (right){
+                (*it)->panel_->setPosition(sin(phi)*radius/
+                    3.5*dim_/2+dim_/2+left_-2,-cos(phi)*radius/3.5*dim_/2+dim_/2+top_-2);
             }
             else {
-                ro->panel_->setPosition(-sin(ro->phi_)*ro->radius_/
-                    3.5*dim_/2+dim_/2+left_-2,-cos(ro->phi_)*ro->radius_/3.5*dim_/2+dim_/2+top_-2);
-            }
-            ro = ro->next;
-		}
-		updateNavMarker();
-    }
-
-    void RadarOverlayElement::updateNavMarker(){
-        if(focus_ == NULL) return;
-        // from the angle we find out where to draw the marker
-        // and which of the four arrows to take
-        float r1 = atan((float)(windowW_)/(float)(windowH_));
-        float phi = focus_->phi_;
-        if(focus_->right_){
-            if(phi<r1){
-                navMarker_->setPosition(tan(phi)*windowH_/2+windowW_/2, 0);
-                navMarker_->setUV(0.5, 0.0, 1.0, 0.5);
-            }
-            else if(phi>3.14-r1){
-                navMarker_->setPosition(-tan(phi)*windowH_/2+windowW_/2, windowH_-16);
-                navMarker_->setUV(0.0, 0.5, 0.5, 1.0);
-            }
-            else {
-                navMarker_->setPosition(windowW_-16, -tan((3.14-2*phi)/2)*windowW_/2+windowH_/2);
-                navMarker_->setUV(0.5, 0.5, 1.0, 1.0);
-            }
-        }
-        else{
-            if(phi<r1) {
-                navMarker_->setPosition(-tan(phi)*windowH_/2+windowW_/2, 0);
-                navMarker_->setUV(0.5, 0.0, 1.0, 0.5);
-            }
-            else if(phi>3.14-r1) {
-                navMarker_->setPosition(tan(phi)*windowH_/2+windowW_/2, windowH_-16);
-                navMarker_->setUV(0.0, 0.5, 0.5, 1.0);
-            }
-            else {
-                navMarker_->setPosition(0, -tan((3.14-2*phi)/2)*windowW_/2+windowH_/2);
-                navMarker_->setUV(0.0, 0.0, 0.5, 0.5);
+                (*it)->panel_->setPosition(-sin(phi)*radius/
+                    3.5*dim_/2+dim_/2+left_-2,-cos(phi)*radius/3.5*dim_/2+dim_/2+top_-2);
             }
         }
     }
 
-    void RadarOverlayElement::addObject(Vector3 pos){
-        if(firstRadarObject_ == NULL){
-            firstRadarObject_ = new RadarObject(container_, pos);
-            lastRadarObject_ = firstRadarObject_;
+    void RadarOverlayElement::listObjects(){
+        int i = 0;
+        COUT(3) << "List of RadarObjects:\n";
+        // iterate through all Radar Objects
+        for(std::set<RadarObject*>::iterator it=HUD::getSingleton().roSet.begin(); it!=HUD::getSingleton().roSet.end(); it++){
+            COUT(3) << i++ << ": " << (*it)->getPosition() << std::endl;
         }
-        else{
-            lastRadarObject_->next = new RadarObject(container_, pos);
-            lastRadarObject_ = lastRadarObject_->next;
-        }
-	}
+    }
 
-	void RadarOverlayElement::listObjects(){
-	    int i = 0;
-	    RadarObject* ro = firstRadarObject_;
-	    COUT(3) << "List of RadarObjects:\n";
-	    // iterate through all Radar Objects
-	    while(ro != NULL) {
-	        COUT(3) << i++ << ": " << ro->pos_ << std::endl;
-	        ro = ro->next;
-	    }
-	}
+    float RadarOverlayElement::calcRadius(Vector3 pos, Vector3 dir, Vector3 orth, RadarObject* obj){
+        return(acos((dir.dotProduct(obj->getPosition() - pos))/
+        ((obj->getPosition() - pos).length()*dir.length())));
+    }
 
-	float RadarOverlayElement::getDist2Focus(){
-	    if(focus_ == NULL) return(0.0);
-	    return((focus_->pos_-shipPos_).length());
-	}
+    float RadarOverlayElement::calcPhi(Vector3 pos, Vector3 dir, Vector3 orth, RadarObject* obj){
+        // project difference vector on our plane...
+        Vector3 proj = Plane(dir, pos).projectVector(obj->getPosition() - pos);
+        // ...and find out the angle
+        return(acos((orth.dotProduct(proj))/
+              (orth.length()*proj.length())));
+    }
 
-	float RadarOverlayElement::calcRadius(RadarObject* obj){
-	    return(acos((currentDir_.dotProduct(obj->pos_ - shipPos_))/
-			((obj->pos_ - shipPos_).length()*currentDir_.length())));
-	}
-
-	float RadarOverlayElement::calcPhi(RadarObject* obj){
-	    // project difference vector on our plane...
-	    Ogre::Vector3 proj = plane.projectVector(obj->pos_ - shipPos_);
-	    // ...and find out the angle
-	    return(acos((currentOrth_.dotProduct(proj))/
-            (currentOrth_.length()*proj.length())));
-	}
-
-	bool RadarOverlayElement::calcRight(RadarObject* obj){
-	    if((currentDir_.crossProduct(currentOrth_)).dotProduct(obj->pos_ - shipPos_) > 0)
-        	return true;
+    bool RadarOverlayElement::calcRight(Vector3 pos, Vector3 dir, Vector3 orth, RadarObject* obj){
+        if((dir.crossProduct(orth)).dotProduct(obj->getPosition() - pos) > 0)
+            return true;
         else return false;
-	}
-
-	/*static*/void RadarOverlayElement::cycleFocus(){
-	    if(RadarOverlayElement::instance_s == NULL) return;
-
-	    if(RadarOverlayElement::instance_s->focus_ == NULL){
-            RadarOverlayElement::instance_s->focus_ = RadarOverlayElement::instance_s->firstRadarObject_;
-	    }
-        else{
-            RadarOverlayElement::instance_s->focus_->panel_->setMaterialName("Orxonox/RedDot");
-            RadarOverlayElement::instance_s->focus_ = RadarOverlayElement::instance_s->focus_->next;
-        }
-
-        if(RadarOverlayElement::instance_s->focus_ == NULL){
-            RadarOverlayElement::instance_s->navMarker_->hide();
-        }
-        else{
-            RadarOverlayElement::instance_s->navMarker_->show();
-            RadarOverlayElement::instance_s->focus_->panel_->setMaterialName("Orxonox/WhiteDot");
-        }
-	}
+    }
 }
-
-/* my local clipboard...
-COUT(3) << "WWWWWWWWWWWWWWWWWWWWWWWWWWWW\n";
-COUT(3) << firstRadarObject_->radius_ << "  " << firstRadarObject_->phi_ << std::endl;
-COUT(3) << "WWWWWWWWWWWWWWWWWWWWWWWWWWWW\n";
-*/
Index: code/trunk/src/orxonox/hud/RadarOverlayElement.h
===================================================================
--- code/trunk/src/orxonox/hud/RadarOverlayElement.h	(revision 1407)
+++ code/trunk/src/orxonox/hud/RadarOverlayElement.h	(revision 1502)
@@ -1,47 +1,38 @@
 /*
-*   ORXONOX - the hottest 3D action shooter ever to exist
-*
-*
-*   License notice:
-*
-*   This program is free software; you can redistribute it and/or
-*   modify it under the terms of the GNU General Public License
-*   as published by the Free Software Foundation; either version 2
-*   of the License, or (at your option) any later version.
-*
-*   This program is distributed in the hope that it will be useful,
-*   but WITHOUT ANY WARRANTY; without even the implied warranty of
-*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-*   GNU General Public License for more details.
-*
-*   You should have received a copy of the GNU General Public License
-*   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:
-*      ...
-*
-*/
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   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
+ *
+ */
 
-#ifndef _RADAR_H__
-#define _RADAR_H__
+#ifndef _RadarOverlayElement_H__
+#define _RadarOverlayElement_H__
 
-#include <string.h>
-#include <OgreOverlayManager.h>
-#include <OgreStringConverter.h>
-#include <OgreOverlayElement.h>
+#include "OrxonoxPrereqs.h"
+
+#include <OgrePrerequisites.h>
 #include <OgrePanelOverlayElement.h>
-#include <OgrePrerequisites.h>
-
-#include <util/Math.h>
-#include <string.h>
-#include "core/Tickable.h"
-#include "core/ConsoleCommand.h"
-#include "objects/SpaceShip.h"
-#include "../OrxonoxPrereqs.h"
-#include "RadarObject.h"
-#include "GraphicsEngine.h"
+#include "util/Math.h"
 
 namespace orxonox
@@ -49,41 +40,28 @@
     class _OrxonoxExport RadarOverlayElement : public Ogre::PanelOverlayElement
     {
-        private:
-            Ogre::OverlayManager* om;               // our one and only overlay manager
-            Ogre::OverlayContainer* container_;     // pointer to the container we're in
-            Vector3 initialDir_;	                // direction of nose
-            Vector3 currentDir_;
-            Vector3 initialOrth_;                   // direction of normal
-            Vector3 currentOrth_;
-            Vector3 shipPos_;                       // position of ship
-            Ogre::Plane plane;                      // plane perpendicular to dir
+      private:
+        Ogre::OverlayManager* om;               // our one and only overlay manager
+        Ogre::OverlayContainer* container_;     // pointer to the container we're in
+        Vector3 currentDir_;
+        Vector3 currentOrth_;
+        Vector3 shipPos_;                       // position of ship
 
-            Ogre::Real leftRel_, topRel_, dimRel_;  // relative position/dimension
-            int left_, top_, dim_;                  // absolute position/dimension
-            int windowW_, windowH_;             	// absolute window dimensions
+        Ogre::Real leftRel_, topRel_, dimRel_;  // relative position/dimension
+        int left_, top_, dim_;                  // absolute position/dimension
+        int windowW_, windowH_;             	  // absolute window dimensions
 
-        public:
-            RadarOverlayElement(const Ogre::String& name);
-            ~RadarOverlayElement();
-            void init(Real leftRel, Real topRel, Real dimRel, Ogre::OverlayContainer* container);
-			void resize();
-            void update();
-            void updateNavMarker();
-            void addObject(Vector3 pos);
-            void listObjects();
-            float getDist2Focus();
-            float calcRadius(RadarObject* obj);
-            float calcPhi(RadarObject* obj);
-            bool calcRight(RadarObject* obj);
+      public:
+        RadarOverlayElement(const Ogre::String& name);
+        ~RadarOverlayElement();
+        void init(Real leftRel, Real topRel, Real dimRel, Ogre::OverlayContainer* container);
+        void resize();
+        void update();
+        void listObjects();
 
-            Ogre::PanelOverlayElement* navMarker_;  // marker to help navigating
-			RadarObject* firstRadarObject_;         // start of linked list
-			RadarObject* lastRadarObject_;          // end of linked list
-			RadarObject* focus_;                    // object that is focussed
-
-            static RadarOverlayElement* instance_s;
-            static void cycleFocus();
-	};
+        static float calcRadius(Vector3 pos, Vector3 dir, Vector3 orth, RadarObject* obj);
+        static float calcPhi(Vector3 pos, Vector3 dir, Vector3 orth, RadarObject* obj);
+        static bool calcRight(Vector3 pos, Vector3 dir, Vector3 orth, RadarObject* obj);
+  };
 }
 
-#endif
+#endif /* _RadarOverlayElement_H__ */
Index: code/trunk/src/orxonox/objects/Ambient.cc
===================================================================
--- code/trunk/src/orxonox/objects/Ambient.cc	(revision 1407)
+++ code/trunk/src/orxonox/objects/Ambient.cc	(revision 1502)
@@ -47,5 +47,5 @@
 namespace orxonox
 {
-    ConsoleCommand(Ambient, setAmbientLightTest, AccessLevel::Offline, false).setDefaultValues(ColourValue(1, 1, 1, 1));
+    SetConsoleCommand(Ambient, setAmbientLightTest, false).setDefaultValues(ColourValue(1, 1, 1, 1)).setAccessLevel(AccessLevel::Offline);
 
     CreateFactory(Ambient);
@@ -66,5 +66,5 @@
     bool Ambient::create(){
       GraphicsEngine::getSingleton().getSceneManager()->setAmbientLight(ambientLight_);
-      return true;
+      return Synchronisable::create();
     }
     
Index: code/trunk/src/orxonox/objects/Ambient.h
===================================================================
--- code/trunk/src/orxonox/objects/Ambient.h	(revision 1407)
+++ code/trunk/src/orxonox/objects/Ambient.h	(revision 1502)
@@ -47,5 +47,5 @@
             virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode);
             void setAmbientLight(const ColourValue& colour);
-            bool create();
+            virtual bool create();
             void registerAllVariables();
 
Index: code/trunk/src/orxonox/objects/Camera.cc
===================================================================
--- code/trunk/src/orxonox/objects/Camera.cc	(revision 1407)
+++ code/trunk/src/orxonox/objects/Camera.cc	(revision 1502)
@@ -60,4 +60,5 @@
   {
     CameraHandler::getInstance()->releaseFocus(this);
+    GraphicsEngine::getSingleton().getSceneManager()->getRootSceneNode()->removeAndDestroyChild(cameraNode_->getName());
   }
 
@@ -75,10 +76,15 @@
   void Camera::tick(float dt)
   {
-    if(this->positionNode_ != NULL) {
+    if (this->positionNode_ != NULL)
+    {
       // this stuff here may need some adjustments
-      Vector3 offset = this->positionNode_->getWorldPosition() - this->cameraNode_->getPosition();
-      this->cameraNode_->translate(15*dt*offset);
+      Vector3 offset = this->positionNode_->getWorldPosition() - this->cameraNode_->getWorldPosition();
+      float coeff = 15.0f * dt;
+      if (coeff > 1.0f)
+        coeff = 1.0f;
 
-      this->cameraNode_->setOrientation(Quaternion::Slerp(0.7, this->positionNode_->getWorldOrientation(), this->cameraNode_->getWorldOrientation(), false));
+      this->cameraNode_->translate(coeff * offset);
+
+      this->cameraNode_->setOrientation(Quaternion::Slerp(7.0f * dt, this->positionNode_->getWorldOrientation(), this->cameraNode_->getWorldOrientation(), false));
     }
   }
Index: code/trunk/src/orxonox/objects/Camera.h
===================================================================
--- code/trunk/src/orxonox/objects/Camera.h	(revision 1407)
+++ code/trunk/src/orxonox/objects/Camera.h	(revision 1502)
@@ -50,4 +50,6 @@
         void setTargetNode(Ogre::SceneNode* obj);
 
+        Ogre::Camera* cam_;
+
         void tick(float dt);
         void update();
@@ -63,5 +65,4 @@
         Ogre::SceneNode* cameraNode_;
         Ogre::Vector3 oldPos;
-        Ogre::Camera* cam_;
         bool bHasFocus_;
     };
Index: code/trunk/src/orxonox/objects/CameraHandler.cc
===================================================================
--- code/trunk/src/orxonox/objects/CameraHandler.cc	(revision 1407)
+++ code/trunk/src/orxonox/objects/CameraHandler.cc	(revision 1502)
@@ -26,10 +26,11 @@
  *
  */
+#include "OrxonoxStableHeaders.h"
+#include "CameraHandler.h"
+
 #include <OgreSceneManager.h>
 #include <OgreRenderWindow.h>
 
-#include "OrxonoxStableHeaders.h"
 #include "core/ObjectList.h"
-#include "CameraHandler.h"
 #include "Camera.h"
 #include "GraphicsEngine.h"
Index: code/trunk/src/orxonox/objects/Explosion.cc
===================================================================
--- code/trunk/src/orxonox/objects/Explosion.cc	(revision 1407)
+++ code/trunk/src/orxonox/objects/Explosion.cc	(revision 1502)
@@ -79,4 +79,10 @@
         }
     };
+    
+    /*bool Explosion::create(){
+      if(!WorldEntity::create())
+        return false;
+      classID=this->getIdentifier()->getNetworkID();
+    }*/
 
     void Explosion::destroyObject()
Index: code/trunk/src/orxonox/objects/Explosion.h
===================================================================
--- code/trunk/src/orxonox/objects/Explosion.h	(revision 1407)
+++ code/trunk/src/orxonox/objects/Explosion.h	(revision 1502)
@@ -43,4 +43,5 @@
             virtual ~Explosion();
             void destroyObject();
+            virtual bool create(){return WorldEntity::create();}
 
         private:
Index: code/trunk/src/orxonox/objects/Model.cc
===================================================================
--- code/trunk/src/orxonox/objects/Model.cc	(revision 1407)
+++ code/trunk/src/orxonox/objects/Model.cc	(revision 1502)
@@ -34,4 +34,10 @@
 #include "GraphicsEngine.h"
 #include "core/XMLPort.h"
+
+#include <OgreEntity.h>
+#include <OgreMesh.h>
+#include <OgreHardwareVertexBuffer.h>
+#include <OgreMeshManager.h>
+
 
 namespace orxonox
@@ -77,4 +83,26 @@
         this->mesh_.setMesh(meshSrc_);
         this->attachObject(this->mesh_.getEntity());
+
+        //HACK!!
+        /*if ((this->meshSrc_ == "assff.mesh") || (this->meshSrc_ == "ast1.mesh") || (this->meshSrc_ == "ast2.mesh") || (this->meshSrc_ == "ast3.mesh") || (this->meshSrc_ == "ast4.mesh") ||(this->meshSrc_ == "ast5.mesh") || (this->meshSrc_ == "ast6.mesh"))
+        {
+          Ogre::MeshPtr pMesh = this->mesh_.getEntity()->getMesh();
+          //set Mesh to tangentspace 
+          unsigned short src, dest;
+          if (!pMesh->suggestTangentVectorBuildParams(Ogre::VES_TANGENT, src, dest))
+          {
+            pMesh->buildTangentVectors(Ogre::VES_TANGENT, src, dest);
+          }
+          if ((this->meshSrc_ == "assff.mesh"))
+          {
+            (this->mesh_.getEntity())->setMaterialName("Assff/BumpMap");
+          }
+          else
+          {
+            (this->mesh_.getEntity())->setMaterialName("Asteroid/BumpMap");
+          }
+
+
+        }*/
         COUT(4) << "Loader (Model.cc): Created model" << std::endl;
       }
Index: code/trunk/src/orxonox/objects/Model.h
===================================================================
--- code/trunk/src/orxonox/objects/Model.h	(revision 1407)
+++ code/trunk/src/orxonox/objects/Model.h	(revision 1502)
@@ -45,5 +45,5 @@
             virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode);
             void setMesh(const std::string& meshname);
-            bool create();
+            virtual bool create();
 
         protected:
Index: code/trunk/src/orxonox/objects/NPC.cc
===================================================================
--- code/trunk/src/orxonox/objects/NPC.cc	(revision 1407)
+++ code/trunk/src/orxonox/objects/NPC.cc	(revision 1502)
@@ -67,8 +67,4 @@
   }
   
-  bool NPC::create(){
-    Model::create();
-    return true;
-  }
 
   /**
Index: code/trunk/src/orxonox/objects/NPC.h
===================================================================
--- code/trunk/src/orxonox/objects/NPC.h	(revision 1407)
+++ code/trunk/src/orxonox/objects/NPC.h	(revision 1502)
@@ -53,5 +53,5 @@
       void setValues(Vector3 location, Vector3 speed, Vector3 acceleration, bool movable);
       void registerAllVariables();
-      bool create();
+      virtual bool create(){return Model::create();}
 
     private:
Index: code/trunk/src/orxonox/objects/Projectile.cc
===================================================================
--- code/trunk/src/orxonox/objects/Projectile.cc	(revision 1407)
+++ code/trunk/src/orxonox/objects/Projectile.cc	(revision 1502)
@@ -30,4 +30,6 @@
 #include "Projectile.h"
 
+#include <OgreBillboard.h>
+
 #include "core/CoreIncludes.h"
 #include "core/Executor.h"
@@ -41,4 +43,6 @@
 {
     CreateFactory(Projectile);
+
+    float Projectile::speed_ = 0;
 
     Projectile::Projectile(SpaceShip* owner) :
@@ -63,5 +67,4 @@
 
         this->destroyTimer_.setTimer(this->lifetime_, false, this, createExecutor(createFunctor(&Projectile::destroyObject)));
-        this->classID = this->getIdentifier()->getNetworkID(); // TODO: remove this hack
 //        COUT(3) << this->classID << std::endl;
     }
@@ -92,5 +95,6 @@
                 if (this->getPosition().squaredDistance(it->getPosition()) <= (radius*radius))
                 {
-                    new Explosion(this);
+                    Explosion *exp = new Explosion(this);
+                    exp->create();
                     delete this;
                     return;
@@ -104,3 +108,8 @@
         delete this;
     }
+
+    void Projectile::setColour(const ColourValue& colour)
+    {
+        this->billboard_.getBillboardSet()->getBillboard(0)->setColour(colour);
+    }
 }
Index: code/trunk/src/orxonox/objects/Projectile.h
===================================================================
--- code/trunk/src/orxonox/objects/Projectile.h	(revision 1407)
+++ code/trunk/src/orxonox/objects/Projectile.h	(revision 1502)
@@ -35,4 +35,5 @@
 #include "../tools/BillboardSet.h"
 #include "../tools/Timer.h"
+#include "util/Math.h"
 
 namespace orxonox
@@ -46,9 +47,16 @@
             void destroyObject();
             virtual void tick(float dt);
+            virtual bool create(){return WorldEntity::create();}
+            void setColour(const ColourValue& colour);
+
+            static float getSpeed()
+                { return Projectile::speed_; }
+
+        protected:
+            SpaceShip* owner_;
 
         private:
-            SpaceShip* owner_;
             BillboardSet billboard_;
-            float speed_;
+            static float speed_;
             float lifetime_;
             Timer<Projectile> destroyTimer_;
Index: code/trunk/src/orxonox/objects/RotatingProjectile.cc
===================================================================
--- code/trunk/src/orxonox/objects/RotatingProjectile.cc	(revision 1502)
+++ code/trunk/src/orxonox/objects/RotatingProjectile.cc	(revision 1502)
@@ -0,0 +1,82 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if 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 "OrxonoxStableHeaders.h"
+#include "RotatingProjectile.h"
+
+#include "core/CoreIncludes.h"
+#include "core/ConfigValueIncludes.h"
+#include <OgreBillboard.h>
+
+namespace orxonox
+{
+    CreateFactory(RotatingProjectile);
+
+    RotatingProjectile::RotatingProjectile(SpaceShip* owner) : Projectile(owner)
+    {
+        RegisterObject(RotatingProjectile);
+
+        this->time_ = 0;
+
+        if (/*this->owner_*/true)
+        {
+            this->rotatingBillboard1_.setBillboardSet("Examples/Flare", ColourValue(1.0, 0.0, 0.0), 1);
+            this->rotatingBillboard2_.setBillboardSet("Examples/Flare", ColourValue(1.0, 0.0, 0.0), 1);
+
+            this->rotatingNode1_ = this->getNode()->createChildSceneNode(this->getName() + "rotating1", Vector3(0, 50, 0));
+            this->rotatingNode2_ = this->getNode()->createChildSceneNode(this->getName() + "rotating2", Vector3(0, -50, 0));
+            this->rotatingNode1_->attachObject(this->rotatingBillboard1_.getBillboardSet());
+            this->rotatingNode2_->attachObject(this->rotatingBillboard2_.getBillboardSet());
+            this->rotatingNode1_->scale(0.3, 0.3, 0.3);
+            this->rotatingNode2_->scale(0.3, 0.3, 0.3);
+        }
+
+        this->setConfigValues();
+    }
+
+    RotatingProjectile::~RotatingProjectile()
+    {
+    }
+
+    void RotatingProjectile::setConfigValues()
+    {
+        SetConfigValue(colour_, ColourValue(1.0, 0.0, 0.0));
+
+        this->rotatingBillboard1_.getBillboardSet()->getBillboard(0)->setColour(this->colour_);
+        this->rotatingBillboard2_.getBillboardSet()->getBillboard(0)->setColour(this->colour_);
+    }
+
+    void RotatingProjectile::tick(float dt)
+    {
+        this->time_ += dt;
+
+        this->rotatingNode1_->setPosition(0, 50 * sin(this->time_ * 20), 50 * cos(this->time_ * 20));
+        this->rotatingNode2_->setPosition(0, -50 * sin(this->time_ * 20), -50 * cos(this->time_ * 20));
+
+        Projectile::tick(dt);
+    }
+}
Index: code/trunk/src/orxonox/objects/RotatingProjectile.h
===================================================================
--- code/trunk/src/orxonox/objects/RotatingProjectile.h	(revision 1502)
+++ code/trunk/src/orxonox/objects/RotatingProjectile.h	(revision 1502)
@@ -0,0 +1,29 @@
+#ifndef _RotatingProjectile_H__
+#define _RotatingProjectile_H__
+
+#include "../OrxonoxPrereqs.h"
+#include "util/Math.h"
+#include "Projectile.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport RotatingProjectile : public Projectile/*, public network::Synchronisable*/
+    {
+        public:
+            RotatingProjectile(SpaceShip* owner = 0);
+            virtual ~RotatingProjectile();
+            void setConfigValues();
+            virtual void tick(float dt);
+            virtual bool create(){return Projectile::create();}
+
+        private:
+            ColourValue colour_;
+            BillboardSet rotatingBillboard1_;
+            BillboardSet rotatingBillboard2_;
+            Ogre::SceneNode* rotatingNode1_;
+            Ogre::SceneNode* rotatingNode2_;
+            float time_;
+    };
+}
+
+#endif /* _RotatingProjectile_H__ */
Index: code/trunk/src/orxonox/objects/Skybox.cc
===================================================================
--- code/trunk/src/orxonox/objects/Skybox.cc	(revision 1407)
+++ code/trunk/src/orxonox/objects/Skybox.cc	(revision 1502)
@@ -90,5 +90,5 @@
     bool Skybox::create(){
       this->setSkybox(skyboxSrc_);
-      return true;
+      return Synchronisable::create();
     }
     
Index: code/trunk/src/orxonox/objects/Skybox.h
===================================================================
--- code/trunk/src/orxonox/objects/Skybox.h	(revision 1407)
+++ code/trunk/src/orxonox/objects/Skybox.h	(revision 1502)
@@ -47,5 +47,5 @@
             void setSkybox(const std::string& skyboxname);
             
-            bool create();
+            virtual bool create();
             void registerAllVariables();
             void setSkyboxSrc(const std::string &src);
Index: code/trunk/src/orxonox/objects/SpaceShip.cc
===================================================================
--- code/trunk/src/orxonox/objects/SpaceShip.cc	(revision 1407)
+++ code/trunk/src/orxonox/objects/SpaceShip.cc	(revision 1502)
@@ -45,15 +45,23 @@
 #include "particle/ParticleInterface.h"
 #include "Projectile.h"
+#include "RotatingProjectile.h"
 #include "core/XMLPort.h"
 #include "core/ConsoleCommand.h"
 #include "network/Client.h"
+#include "hud/HUD.h"
 
 namespace orxonox
 {
-    ConsoleCommand(SpaceShip, setMaxSpeedTest, AccessLevel::Debug, false);
-    ConsoleCommand(SpaceShip, whereAmI, AccessLevel::User, true);
-    ConsoleCommandGeneric(test1, SpaceShip, createExecutor(createFunctor(&SpaceShip::setMaxSpeedTest), "setMaxSpeed", AccessLevel::Debug), false);
-    ConsoleCommandGeneric(test2, SpaceShip, createExecutor(createFunctor(&SpaceShip::setMaxSpeedTest), "setMaxBlubber", AccessLevel::Debug), false);
-    ConsoleCommandGeneric(test3, SpaceShip, createExecutor(createFunctor(&SpaceShip::setMaxSpeedTest), "setRofl", AccessLevel::Debug), false);
+    SetConsoleCommand(SpaceShip, setMaxSpeedTest, false).setAccessLevel(AccessLevel::Debug);
+    SetConsoleCommand(SpaceShip, whereAmI, true).setAccessLevel(AccessLevel::User);
+    SetConsoleCommand(SpaceShip, moveLongitudinal, true).setAccessLevel(AccessLevel::User).setDefaultValue(0, 1.0f).setAxisParamIndex(0).setKeybindMode(KeybindMode::OnHold);
+    SetConsoleCommand(SpaceShip, moveLateral, true).setAccessLevel(AccessLevel::User).setDefaultValue(0, 1.0f).setAxisParamIndex(0).setKeybindMode(KeybindMode::OnHold);
+    SetConsoleCommand(SpaceShip, moveYaw, true).setAccessLevel(AccessLevel::User).setDefaultValue(0, 1.0f).setAxisParamIndex(0).setKeybindMode(KeybindMode::OnHold);
+    SetConsoleCommand(SpaceShip, movePitch, true).setAccessLevel(AccessLevel::User).setDefaultValue(0, 1.0f).setAxisParamIndex(0).setKeybindMode(KeybindMode::OnHold);
+    SetConsoleCommand(SpaceShip, moveRoll, true).setAccessLevel(AccessLevel::User).setDefaultValue(0, 1.0f).setAxisParamIndex(0).setKeybindMode(KeybindMode::OnHold);
+    SetConsoleCommand(SpaceShip, fire, true).setAccessLevel(AccessLevel::User).setKeybindMode(KeybindMode::OnHold);
+    SetConsoleCommandGeneric(test1, SpaceShip, createConsoleCommand(createFunctor(&SpaceShip::setMaxSpeedTest), "setMaxSpeed"), false).setAccessLevel(AccessLevel::Debug);
+    SetConsoleCommandGeneric(test2, SpaceShip, createConsoleCommand(createFunctor(&SpaceShip::setMaxSpeedTest), "setMaxBlubber"), false).setAccessLevel(AccessLevel::Debug);
+    SetConsoleCommandGeneric(test3, SpaceShip, createConsoleCommand(createFunctor(&SpaceShip::setMaxSpeedTest), "setRofl"), false).setAccessLevel(AccessLevel::Debug);
 
     CreateFactory(SpaceShip);
@@ -64,10 +72,10 @@
       Iterator<SpaceShip> it;
       for(it = ObjectList<SpaceShip>::start(); it; ++it){
-        if((it)->server_ || ( network::Client::getSingleton() && network::Client::getSingleton()->getShipID()==it->objectID ) )
+        if( (it)->myShip_ )
           return *it;
       }
       return NULL;
     }
-    
+
     SpaceShip::SpaceShip() :
       //testvector_(0,0,0),
@@ -103,5 +111,7 @@
       mouseY_(0.0f),
       emitterRate_(0.0f),
-      server_(false)
+      myShip_(false),
+      teamNr_(0),
+      health_(100)
     {
         RegisterObject(SpaceShip);
@@ -112,4 +122,10 @@
         this->setConfigValues();
 
+        initialDir_ = Vector3(1.0, 0.0, 0.0);
+        currentDir_ = initialDir_;
+        initialOrth_ = Vector3(0.0, 0.0, 1.0);
+        currentOrth_ = initialOrth_;
+
+        this->camName_ = this->getName() + "CamNode";
 
         this->setRotationAxis(1, 0, 0);
@@ -127,7 +143,16 @@
         if (this->cam_)
           delete this->cam_;
+        if (!Identifier::isCreatingHierarchy() && !myShip_ && &HUD::getSingleton()!=NULL)
+          //remove the radar object
+          HUD::getSingleton().removeRadarObject(this->getNode());
     }
 
     bool SpaceShip::create(){
+      if(!myShip_){
+        if(network::Client::getSingleton() && objectID == network::Client::getSingleton()->getShipID())
+          myShip_=true;
+        else
+          HUD::getSingleton().addRadarObject(this->getNode(), 3);
+      }
       if(Model::create())
         this->init();
@@ -153,14 +178,4 @@
     void SpaceShip::init()
     {
-        if ((server_ || ( network::Client::getSingleton() && network::Client::getSingleton()->getShipID()==objectID ) ))
-        {
-              if (!setMouseEventCallback_)
-              {
-                  InputManager::addMouseHandler(this, "SpaceShip");
-                  //InputManager::enableMouseHandler("SpaceShip");
-                  setMouseEventCallback_ = true;
-              }
-        }
-
         // START CREATING THRUSTER
         this->tt_ = new ParticleInterface(GraphicsEngine::getSingleton().getSceneManager(),"twinthruster" + this->getName(),"Orxonox/engineglow");
@@ -200,18 +215,21 @@
         // END CREATING BLINKING LIGHTS
 
-        // START of testing crosshair
-        this->crosshairNear_.setBillboardSet("Orxonox/Crosshair", ColourValue(1.0, 1.0, 0.0), 1);
-        this->crosshairFar_.setBillboardSet("Orxonox/Crosshair", ColourValue(1.0, 1.0, 0.0), 1);
-
-        this->chNearNode_ = this->getNode()->createChildSceneNode(this->getName() + "near", Vector3(50.0, 0.0, 0.0));
-        this->chNearNode_->setInheritScale(false);
-        this->chFarNode_ = this->getNode()->createChildSceneNode(this->getName() + "far", Vector3(200.0, 0.0, 0.0));
-        this->chFarNode_->setInheritScale(false);
-
-        this->chNearNode_->attachObject(this->crosshairNear_.getBillboardSet());
-        this->chNearNode_->setScale(0.2, 0.2, 0.2);
-
-        this->chFarNode_->attachObject(this->crosshairFar_.getBillboardSet());
-        this->chFarNode_->setScale(0.4, 0.4, 0.4);
+        if (this->isExactlyA(Class(SpaceShip)))
+        {
+            // START of testing crosshair
+            this->crosshairNear_.setBillboardSet("Orxonox/Crosshair", ColourValue(1.0, 1.0, 0.0), 1);
+            this->crosshairFar_.setBillboardSet("Orxonox/Crosshair", ColourValue(1.0, 1.0, 0.0), 1);
+
+            this->chNearNode_ = this->getNode()->createChildSceneNode(this->getName() + "near", Vector3(50.0, 0.0, 0.0));
+            this->chNearNode_->setInheritScale(false);
+            this->chFarNode_ = this->getNode()->createChildSceneNode(this->getName() + "far", Vector3(200.0, 0.0, 0.0));
+            this->chFarNode_->setInheritScale(false);
+
+            this->chNearNode_->attachObject(this->crosshairNear_.getBillboardSet());
+            this->chNearNode_->setScale(0.2, 0.2, 0.2);
+
+            this->chFarNode_->attachObject(this->crosshairFar_.getBillboardSet());
+            this->chFarNode_->setScale(0.4, 0.4, 0.4);
+        }
 
         createCamera();
@@ -237,4 +255,8 @@
         CameraHandler::getInstance()->requestFocus(cam_);
 
+    }
+
+    Camera* SpaceShip::getCamera(){
+        return cam_;
     }
 
@@ -295,7 +317,9 @@
         XMLPortParamLoadOnly(SpaceShip, "transDamp", setTransDamp, xmlelement, mode);
         XMLPortParamLoadOnly(SpaceShip, "rotDamp", setRotDamp, xmlelement, mode);
-        server_=true; // TODO: this is only a hack
+        myShip_=true; // TODO: this is only a hack
+
         SpaceShip::create();
-        getFocus();
+        if (this->isExactlyA(Class(SpaceShip)))
+            getFocus();
     }
 
@@ -308,81 +332,4 @@
     }
 
-    void SpaceShip::mouseMoved(IntVector2 abs, IntVector2 rel, IntVector2 clippingSize)
-    {
-/*
-        this->mouseX += e.state.X.rel;
-        if (this->bInvertMouse_)
-            this->mouseY += e.state.Y.rel;
-        else
-            this->mouseY -= e.state.Y.rel;
-
-//        if(mouseX>maxMouseX) maxMouseX = mouseX;
-//        if(mouseX<minMouseX) minMouseX = mouseX;
-//        cout << "mouseX: " << mouseX << "\tmouseY: " << mouseY << endl;
-
-        this->moved = true;
-*/
-        if (this->bRMousePressed_)
-        {
-            this->camNode_->roll(Degree(-rel.x * 0.10));
-            this->camNode_->yaw(Degree(rel.y * 0.10));
-        }
-        else
-        {
-            float minDimension = clippingSize.y;
-            if (clippingSize.x < minDimension)
-                minDimension = clippingSize.x;
-
-            this->mouseX_ += rel.x;
-            if (this->mouseX_ < -minDimension)
-                this->mouseX_ = -minDimension;
-            if (this->mouseX_ > minDimension)
-                this->mouseX_ = minDimension;
-
-            this->mouseY_ += rel.y;
-            if (this->mouseY_ < -minDimension)
-                this->mouseY_ = -minDimension;
-            if (this->mouseY_ > minDimension)
-                this->mouseY_ = minDimension;
-
-            float xRotation = this->mouseX_ / minDimension;
-            xRotation = xRotation*xRotation * sgn(xRotation);
-            xRotation *= -this->rotationAcceleration_;
-            if (xRotation > this->maxRotation_)
-                xRotation = this->maxRotation_;
-            if (xRotation < -this->maxRotation_)
-                xRotation = -this->maxRotation_;
-            this->mouseXRotation_ = Radian(xRotation);
-
-            float yRotation = this->mouseY_ / minDimension;
-            yRotation = yRotation*yRotation * sgn(yRotation);
-            yRotation *= this->rotationAcceleration_;
-            if (yRotation > this->maxRotation_)
-                yRotation = this->maxRotation_;
-            if (yRotation < -this->maxRotation_)
-                yRotation = -this->maxRotation_;
-            this->mouseYRotation_ = Radian(yRotation);
-        }
-    }
-
-    void SpaceShip::mouseButtonPressed(MouseButton::Enum id)
-    {
-        if (id == MouseButton::Left)
-            this->bLMousePressed_ = true;
-        else if (id == MouseButton::Right)
-            this->bRMousePressed_ = true;
-    }
-
-    void SpaceShip::mouseButtonReleased(MouseButton::Enum id)
-    {
-        if (id == MouseButton::Left)
-            this->bLMousePressed_ = false;
-        else if (id == MouseButton::Right)
-        {
-            this->bRMousePressed_ = false;
-            this->camNode_->resetOrientation();
-        }
-    }
-
     std::string SpaceShip::whereAmI() {
 	return getConvertedValue<float, std::string>(SpaceShip::getLocalShip()->getPosition().x)
@@ -391,10 +338,10 @@
     }
 
-    Vector3 SpaceShip::getSPosition() {
-	return SpaceShip::getLocalShip()->getPosition();
-    }
-
-    Quaternion SpaceShip::getSOrientation() {
-	return SpaceShip::getLocalShip()->getOrientation();
+    Vector3 SpaceShip::getDir() {
+        return currentDir_;
+    }
+
+    Vector3 SpaceShip::getOrth(){
+        return currentOrth_;
     }
 
@@ -403,4 +350,7 @@
     void SpaceShip::tick(float dt)
     {
+        currentDir_ = getOrientation()*initialDir_;
+		currentOrth_ = getOrientation()*initialOrth_;
+
         if (this->cam_)
             this->cam_->tick(dt);
@@ -422,7 +372,15 @@
         if (this->bLMousePressed_ && this->timeToReload_ <= 0)
         {
-          
-            Projectile *p = new Projectile(this);
-            
+
+            Projectile *p;
+            if (this->isExactlyA(Class(SpaceShip)))
+                p = new RotatingProjectile(this);
+            else
+                p = new Projectile(this);
+            p->setColour(this->getProjectileColour());
+            p->create();
+            if(p->classID==0)
+              COUT(3) << "generated projectile with classid 0" <<  std::endl; // TODO: remove this output
+
             p->setBacksync(true);
             this->timeToReload_ = this->reloadTime_;
@@ -495,29 +453,4 @@
         }
 
-        if( (network::Client::getSingleton() &&  network::Client::getSingleton()->getShipID() == objectID) || server_ )
-        {
-          COUT(4) << "steering our ship: " << objectID << std::endl;
-          if (InputManager::isKeyDown(KeyCode::Up) || InputManager::isKeyDown(KeyCode::W))
-            this->acceleration_.x = this->translationAcceleration_;
-          else if(InputManager::isKeyDown(KeyCode::Down) || InputManager::isKeyDown(KeyCode::S))
-            this->acceleration_.x = -this->translationAcceleration_;
-          else
-            this->acceleration_.x = 0;
-
-          if (InputManager::isKeyDown(KeyCode::Right) || InputManager::isKeyDown(KeyCode::D))
-            this->acceleration_.y = -this->translationAcceleration_;
-          else if (InputManager::isKeyDown(KeyCode::Left) || InputManager::isKeyDown(KeyCode::A))
-            this->acceleration_.y = this->translationAcceleration_;
-          else
-            this->acceleration_.y = 0;
-
-          if (InputManager::isKeyDown(KeyCode::Delete) || InputManager::isKeyDown(KeyCode::Q))
-            this->momentum_ = Radian(-this->rotationAccelerationRadian_);
-          else if (InputManager::isKeyDown(KeyCode::PageDown) || InputManager::isKeyDown(KeyCode::E))
-            this->momentum_ = Radian(this->rotationAccelerationRadian_);
-          else
-            this->momentum_ = 0;
-        }/*else
-          COUT(4) << "not steering ship: " << objectID << " our ship: " << network::Client::getSingleton()->getShipID() << std::endl;*/
 
         WorldEntity::tick(dt);
@@ -533,5 +466,70 @@
         else
             this->tt_->setRate(0);
-    }
-
+
+        if( myShip_ )
+        {
+          COUT(4) << "steering our ship: " << objectID << std::endl;
+          this->acceleration_.x = 0;
+          this->acceleration_.y = 0;
+          this->momentum_ = 0;
+          this->mouseXRotation_ = Radian(0);
+          this->mouseYRotation_ = Radian(0);
+          this->bLMousePressed_ = false;
+        }/*else
+          COUT(4) << "not steering ship: " << objectID << " our ship: " << network::Client::getSingleton()->getShipID() << std::endl;*/
+    }
+
+    void SpaceShip::movePitch(float val)
+    {   getLocalShip()->setMovePitch(val);   }
+    void SpaceShip::moveYaw(float val)
+    {   getLocalShip()->setMoveYaw(val);   }
+    void SpaceShip::moveRoll(float val)
+    {   getLocalShip()->setMoveRoll(val);   }
+    void SpaceShip::moveLongitudinal(float val)
+    {   getLocalShip()->setMoveLongitudinal(val);   }
+    void SpaceShip::moveLateral(float val)
+    {   getLocalShip()->setMoveLateral(val);   }
+    void SpaceShip::fire()
+    {   getLocalShip()->doFire();   }
+
+    void SpaceShip::setMovePitch(float val)
+    {
+        val = -val * val * sgn(val) * this->rotationAcceleration_;
+        if (val > this->maxRotation_)
+            val = this->maxRotation_;
+        if (val < -this->maxRotation_)
+            val = -this->maxRotation_;
+        this->mouseYRotation_ = Radian(val);
+    }
+
+    void SpaceShip::setMoveYaw(float val)
+    {
+        val = -val * val * sgn(val) * this->rotationAcceleration_;
+        if (val > this->maxRotation_)
+            val = this->maxRotation_;
+        if (val < -this->maxRotation_)
+            val = -this->maxRotation_;
+        this->mouseXRotation_ = Radian(val);
+    }
+
+    void SpaceShip::setMoveRoll(float val)
+    {
+        this->momentum_ = Radian(-this->rotationAccelerationRadian_ * val);
+        //COUT(3) << "rotating val: " << val << " acceleration: " << this->rotationAccelerationRadian_.valueDegrees() << std::endl;
+    }
+
+    void SpaceShip::setMoveLongitudinal(float val)
+    {
+        this->acceleration_.x = this->translationAcceleration_ * val;
+    }
+
+    void SpaceShip::setMoveLateral(float val)
+    {
+        this->acceleration_.y = -this->translationAcceleration_ * val;
+    }
+
+    void SpaceShip::doFire()
+    {
+        this->bLMousePressed_ = true;
+    }
 }
Index: code/trunk/src/orxonox/objects/SpaceShip.h
===================================================================
--- code/trunk/src/orxonox/objects/SpaceShip.h	(revision 1407)
+++ code/trunk/src/orxonox/objects/SpaceShip.h	(revision 1502)
@@ -41,13 +41,13 @@
 namespace orxonox
 {
-    class _OrxonoxExport SpaceShip : public Model, public MouseHandler
+    class _OrxonoxExport SpaceShip : public Model
     {
         public:
-          
+
             static SpaceShip *getLocalShip();
-            
+
             SpaceShip();
             ~SpaceShip();
-            bool create();
+            virtual bool create();
             void registerAllVariables();
             void init();
@@ -64,25 +64,49 @@
             void setTransDamp(float value);
             void setRotDamp(float value);
+            void getFocus();
 
-            void getFocus();
-            static SpaceShip* instance_s;
-            static Vector3 getSPosition();
-            static Quaternion getSOrientation();
             static std::string whereAmI();
             static void setMaxSpeedTest(float value)
                 { SpaceShip::instance_s->setMaxSpeed(value); }
 
-            void mouseButtonPressed (MouseButton::Enum id);
-            void mouseButtonReleased(MouseButton::Enum id);
-            void mouseButtonHeld    (MouseButton::Enum id) { }
-            void mouseMoved         (IntVector2 abs, IntVector2 rel, IntVector2 clippingSize);
-            void mouseScrolled      (int abs, int rel) { }
+            static void movePitch(float value);
+            static void moveYaw(float value);
+            static void moveRoll(float value);
+            static void moveLongitudinal(float value);
+            static void moveLateral(float value);
+            static void fire();
+            void setMovePitch(float value);
+            void setMoveYaw(float value);
+            void setMoveRoll(float value);
+            void setMoveLongitudinal(float value);
+            void setMoveLateral(float value);
+            void doFire();
 
             float getMaxSpeed();
+            Vector3 getDir();
+            Vector3 getOrth();
+            Camera* getCamera();
+
+            int getTeamNr() const
+                { return this->teamNr_; }
+            int getHealth() const
+                { return this->health_; }
+
+            bool getMyShip(){return myShip_;}
+
+        protected:
+            void setTeamNr(int teamNr)
+                { this->teamNr_ = teamNr; }
 
         private:
             void createCamera();
+            virtual ColourValue getProjectileColour() const
+                { return ColourValue(1.0, 1.0, 0.5); }
 
             Vector3 testvector_;
+            Vector3 initialDir_;
+            Vector3 currentDir_;
+            Vector3 initialOrth_;
+            Vector3 currentOrth_;
             bool bInvertYAxis_;
             bool setMouseEventCallback_;
@@ -130,5 +154,12 @@
 
             float emitterRate_;
-            bool server_;
+
+        protected:
+            bool myShip_;
+
+            int teamNr_;
+            int health_;
+
+            static SpaceShip* instance_s;
     };
 }
Index: code/trunk/src/orxonox/objects/SpaceShipAI.cc
===================================================================
--- code/trunk/src/orxonox/objects/SpaceShipAI.cc	(revision 1502)
+++ code/trunk/src/orxonox/objects/SpaceShipAI.cc	(revision 1502)
@@ -0,0 +1,293 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if 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 "OrxonoxStableHeaders.h"
+#include "SpaceShipAI.h"
+
+#include <OgreMath.h>
+#include "Projectile.h"
+#include "core/CoreIncludes.h"
+#include "core/Iterator.h"
+#include "core/Executor.h"
+#include "core/ConsoleCommand.h"
+#include "core/XMLPort.h"
+
+#define ACTION_INTERVAL 1.0f
+
+namespace orxonox
+{
+    SetConsoleCommand(SpaceShipAI, createEnemy, true).setDefaultValue(0, 1);
+    SetConsoleCommand(SpaceShipAI, killEnemies, true).setDefaultValue(0, 0);
+
+    CreateFactory(SpaceShipAI);
+
+    SpaceShipAI::SpaceShipAI()
+    {
+        RegisterObject(SpaceShipAI);
+
+        this->alive_ = true;
+        this->setPosition(Vector3(rnd(-1000, 1000), rnd(-1000, 1000), rnd(-1000, 0000)));
+        this->target_ = 0;
+        this->bShooting_ = 0;
+        this->bHasTargetPosition_ = false;
+
+        this->setTeamNr((int)rnd(NUM_AI_TEAMS) % NUM_AI_TEAMS + 1);
+
+        if (NUM_AI_TEAMS > 0)
+            this->teamColours_[1] = ColourValue(1, 0, 0, 1);
+        if (NUM_AI_TEAMS > 1)
+            this->teamColours_[2] = ColourValue(0, 1, 0, 1);
+        if (NUM_AI_TEAMS > 2)
+            this->teamColours_[3] = ColourValue(0, 0, 1, 1);
+
+        for (int i = 4; i <= NUM_AI_TEAMS; ++i)
+            this->teamColours_[i] = ColourValue(rnd(), rnd(), rnd(), 1);
+    }
+
+    void SpaceShipAI::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SpaceShip::XMLPort(xmlelement, mode);
+        myShip_=true;
+
+        this->actionTimer_.setTimer(ACTION_INTERVAL, true, this, createExecutor(createFunctor(&SpaceShipAI::action)));
+    }
+
+    void SpaceShipAI::createEnemy(int num)
+    {
+        for (int i = 0; i < num; ++i)
+        {
+            SpaceShipAI* newenemy = new SpaceShipAI();
+            newenemy->setMesh("assff.mesh");
+//            newenemy->setPosition(0, 0, 0);
+            newenemy->setScale(10);
+            newenemy->setMaxSpeed(500);
+            newenemy->setMaxSideAndBackSpeed(50);
+            newenemy->setMaxRotation(1.0);
+            newenemy->setTransAcc(200);
+            newenemy->setRotAcc(3.0);
+            newenemy->setTransDamp(75);
+            newenemy->setRotDamp(1.0);
+            Element xmlelement;
+            newenemy->XMLPort(xmlelement, XMLPort::LoadObject);
+        }
+    }
+
+    void SpaceShipAI::killEnemies(int num)
+    {
+        int i = 0;
+        for (Iterator<SpaceShipAI> it = ObjectList<SpaceShipAI>::begin(); it; )
+        {
+            delete *(it++);
+            ++i;
+            if (num && i >= num)
+                break;
+        }
+    }
+
+    ColourValue SpaceShipAI::getProjectileColour() const
+    {
+        return this->teamColours_[this->getTeamNr()];
+    }
+
+    void SpaceShipAI::action()
+    {
+        float random;
+        float maxrand = 100.0f / ACTION_INTERVAL;
+
+        // search enemy
+        random = rnd(maxrand);
+//std::cout << "search enemy: " << random << std::endl;
+        if (random < 20 && (!this->target_))
+        {
+            this->searchNewTarget();
+        }
+
+        // forget enemy
+        random = rnd(maxrand);
+//std::cout << "forget enemy: " << random << std::endl;
+        if (random < 5 && (this->target_))
+        {
+            this->forgetTarget();
+        }
+
+        // next enemy
+        random = rnd(maxrand);
+//std::cout << "next enemy: " << random << std::endl;
+        if (random < 10 && (this->target_))
+        {
+            this->searchNewTarget();
+        }
+
+        // fly somewhere
+        random = rnd(maxrand);
+//std::cout << "fly somewhere: " << random << std::endl;
+        if (random < 40 && (!this->bHasTargetPosition_ && !this->target_))
+        {
+            this->searchNewTargetPosition();
+        }
+
+        // stop flying
+        random = rnd(maxrand);
+//std::cout << "stop flying: " << random << std::endl;
+        if (random < 10 && (this->bHasTargetPosition_ && !this->target_))
+        {
+            this->bHasTargetPosition_ = false;
+        }
+
+        // fly somewhere else
+        random = rnd(maxrand);
+//std::cout << "fly somewhere else: " << random << std::endl;
+        if (random < 30 && (this->bHasTargetPosition_ && !this->target_))
+        {
+            this->searchNewTargetPosition();
+        }
+
+        // shoot
+        random = rnd(maxrand);
+//std::cout << "shoot: " << random << std::endl;
+        if (random < 75 && (this->target_ && !this->bShooting_))
+        {
+            this->bShooting_ = true;
+        }
+
+        // stop shooting
+        random = rnd(maxrand);
+//std::cout << "stop shooting: " << random << std::endl;
+        if (random < 25 && (this->bShooting_))
+        {
+            this->bShooting_ = false;
+        }
+    }
+
+    void SpaceShipAI::tick(float dt)
+    {
+        if (this->target_)
+            this->aimAtTarget();
+
+        if (this->bHasTargetPosition_)
+            this->moveToTargetPosition(dt);
+
+        if (this->bShooting_ && this->isCloseAtTarget(2000) && this->isLookingAtTarget(Ogre::Math::PI / 10.0f))
+            this->doFire();
+
+        SpaceShip::tick(dt);
+    }
+
+    void SpaceShipAI::moveToTargetPosition(float dt)
+    {
+        static Radian RadianZERO(0);
+
+//        float dotprod = (this->getOrientation() * Ogre::Vector3::UNIT_X).dotProduct(this->targetPosition_ - this->getPosition());
+        Quaternion rotation = (this->getOrientation() * Ogre::Vector3::UNIT_X).getRotationTo(this->targetPosition_ - this->getPosition());
+/*
+std::cout << "scalprod: " << dotprod << std::endl;
+std::cout << "dist: " << this->targetPosition_ - this->getPosition() << std::endl;
+std::cout << "yaw: " << rotation.getYaw().valueRadians() << std::endl;
+std::cout << "pitch: " << rotation.getPitch().valueRadians() << std::endl;
+std::cout << "roll: " << rotation.getRoll().valueRadians() << std::endl;
+*/
+        this->setMoveYaw(-rotation.getRoll().valueRadians());
+        this->setMovePitch(rotation.getYaw().valueRadians());
+
+        if ((this->targetPosition_ - this->getPosition()).length() > 100)
+        {
+            this->setMoveLongitudinal(1);
+        }
+
+    }
+
+    void SpaceShipAI::searchNewTargetPosition()
+    {
+        this->targetPosition_ = Vector3(rnd(-5000,5000), rnd(-5000,5000), rnd(-5000,5000));
+        this->bHasTargetPosition_ = true;
+    }
+
+    void SpaceShipAI::searchNewTarget()
+    {
+        this->targetPosition_ = this->getPosition();
+        this->forgetTarget();
+
+        for (Iterator<SpaceShip> it = ObjectList<SpaceShip>::begin(); it; ++it)
+        {
+            if (it->getTeamNr() != this->getTeamNr())
+            {
+                float speed = this->getVelocity().length();
+                Vector3 distanceCurrent = this->targetPosition_ - this->getPosition();
+                Vector3 distanceNew = it->getPosition() - this->getPosition();
+                if (!this->target_ || it->getPosition().squaredDistance(this->getPosition()) * (1.5f + acos((this->getOrientation() * Ogre::Vector3::UNIT_X).dotProduct(distanceNew) / speed / distanceNew.length()) / (2 * Ogre::Math::PI))
+                        < this->targetPosition_.squaredDistance(this->getPosition()) * (1.5f + acos((this->getOrientation() * Ogre::Vector3::UNIT_X).dotProduct(distanceCurrent) / speed / distanceCurrent.length()) / (2 * Ogre::Math::PI)))
+                {
+                    this->target_ = (*it);
+                    this->targetPosition_ = it->getPosition();
+                }
+            }
+        }
+   }
+
+    void SpaceShipAI::forgetTarget()
+    {
+        this->target_ = 0;
+        this->bShooting_ = false;
+    }
+
+    void SpaceShipAI::aimAtTarget()
+    {
+        if (!this->target_)
+            return;
+/*
+        Vector3 enemymovement = this->target_->getVelocity();
+        Vector3 distance_normalised = this->target_->getPosition() - this->getPosition();
+        distance_normalised.normalise();
+
+        float scalarprod = enemymovement.dotProduct(distance_normalised);
+        float aimoffset = scalarprod*scalarprod + Projectile::getSpeed() * Projectile::getSpeed() - this->target_->getVelocity().squaredLength();
+        if (aimoffset < 0)
+        {
+            this->bHasTargetPosition_ = false;
+            return;
+        }
+        aimoffset = -scalarprod + sqrt(aimoffset);
+        this->targetPosition_ = enemymovement + distance_normalised * aimoffset;
+        this->bHasTargetPosition_ = true;
+
+        std::cout << "targetpos: " << this->targetPosition_ << std::endl;
+*/
+        this->targetPosition_ = this->target_->getPosition();
+        this->bHasTargetPosition_ = true;
+    }
+
+    bool SpaceShipAI::isCloseAtTarget(float distance)
+    {
+        return (this->getPosition().squaredDistance(this->targetPosition_) < distance*distance);
+    }
+
+    bool SpaceShipAI::isLookingAtTarget(float angle)
+    {
+        return (this->getOrientation() * Ogre::Vector3::UNIT_X).directionEquals(this->targetPosition_ - this->getPosition(), Radian(angle));
+    }
+}
Index: code/trunk/src/orxonox/objects/SpaceShipAI.h
===================================================================
--- code/trunk/src/orxonox/objects/SpaceShipAI.h	(revision 1502)
+++ code/trunk/src/orxonox/objects/SpaceShipAI.h	(revision 1502)
@@ -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 _SpaceShipAI_H__
+#define _SpaceShipAI_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include "SpaceShip.h"
+#include "tools/Timer.h"
+#include "util/Math.h"
+
+#define NUM_AI_TEAMS 3
+
+namespace orxonox
+{
+    class SpaceShipAI : public SpaceShip
+    {
+        public:
+            SpaceShipAI();
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode);
+            static void createEnemy(int num);
+            static void killEnemies(int num);
+
+        private:
+            virtual void tick(float dt);
+            virtual ColourValue getProjectileColour() const;
+
+            void action();
+
+            void moveToTargetPosition(float dt);
+            void searchNewTargetPosition();
+            void forgetTarget();
+            void searchNewTarget();
+            void aimAtTarget();
+            bool isCloseAtTarget(float distance);
+            bool isLookingAtTarget(float angle);
+
+            Timer<SpaceShipAI> actionTimer_;
+
+            bool alive_;
+            bool bHasTargetPosition_;
+            Vector3 targetPosition_;
+            SpaceShip* target_;
+            bool bShooting_;
+
+            ColourValue teamColours_[NUM_AI_TEAMS + 1];
+    };
+}
+
+#endif /* _SpaceShipAI_H__ */
Index: code/trunk/src/orxonox/objects/WorldEntity.cc
===================================================================
--- code/trunk/src/orxonox/objects/WorldEntity.cc	(revision 1407)
+++ code/trunk/src/orxonox/objects/WorldEntity.cc	(revision 1502)
@@ -85,4 +85,5 @@
             this->rotationRate_ += (dt * this->momentum_);
             this->rotate(this->rotationAxis_, dt * this->rotationRate_);
+            //COUT(3) << "rotationrate: " << this->rotationRate_.valueDegrees() << " momentum: " << this->momentum_.valueDegrees() << std::endl;
         }
     }
@@ -153,8 +154,8 @@
       registerVar( (void*) &(this->bStatic_), sizeof(this->bStatic_), network::DATA, 0x3);
       //register acceleration & momentum
-      registerVar( (void*) &(this->getAcceleration().x), sizeof(this->getAcceleration().x), network::DATA, 0x3);
-      registerVar( (void*) &(this->getAcceleration().y), sizeof(this->getAcceleration().y), network::DATA, 0x3);
-      registerVar( (void*) &(this->getAcceleration().z), sizeof(this->getAcceleration().z), network::DATA, 0x3);
-      registerVar( (void*) &(this->getMomentum()), sizeof(this->getMomentum()), network::DATA);
+//       registerVar( (void*) &(this->getAcceleration().x), sizeof(this->getAcceleration().x), network::DATA, 0x2);
+//       registerVar( (void*) &(this->getAcceleration().y), sizeof(this->getAcceleration().y), network::DATA, 0x2);
+//       registerVar( (void*) &(this->getAcceleration().z), sizeof(this->getAcceleration().z), network::DATA, 0x2);
+//       registerVar( (void*) &(this->getMomentum()), sizeof(this->getMomentum()), network::DATA, 0x2); // only backsync
     }
 
Index: code/trunk/src/orxonox/objects/WorldEntity.h
===================================================================
--- code/trunk/src/orxonox/objects/WorldEntity.h	(revision 1407)
+++ code/trunk/src/orxonox/objects/WorldEntity.h	(revision 1502)
@@ -53,5 +53,5 @@
             virtual void loadParams(TiXmlElement* xmlElem);
             virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode);
-            inline bool create(){ return true; }
+            virtual inline bool create(){ return Synchronisable::create(); }
 
             void attachWorldEntity(WorldEntity* entity);
Index: code/trunk/src/orxonox/objects/weapon/AmmunitionDump.h
===================================================================
--- code/trunk/src/orxonox/objects/weapon/AmmunitionDump.h	(revision 1407)
+++ code/trunk/src/orxonox/objects/weapon/AmmunitionDump.h	(revision 1502)
@@ -60,5 +60,5 @@
 
   protected:
-    inline bool create() { return true; }
+    inline bool create() { return Synchronisable::create(); }
     void registerAllVariables();
 
Index: code/trunk/src/orxonox/objects/weapon/BulletManager.h
===================================================================
--- code/trunk/src/orxonox/objects/weapon/BulletManager.h	(revision 1407)
+++ code/trunk/src/orxonox/objects/weapon/BulletManager.h	(revision 1502)
@@ -60,5 +60,5 @@
 
   protected:
-    inline bool create() { return true; }
+    inline bool create() { return Synchronisable::create(); }
     void registerAllVariables();
 
Index: code/trunk/src/orxonox/tools/Mesh.cc
===================================================================
--- code/trunk/src/orxonox/tools/Mesh.cc	(revision 1407)
+++ code/trunk/src/orxonox/tools/Mesh.cc	(revision 1502)
@@ -40,7 +40,7 @@
     unsigned int Mesh::meshCounter_s = 0;
 
-    Mesh::Mesh()
+    Mesh::Mesh() :
+      entity_(0)
     {
-        this->entity_ = 0;
     }
 
Index: code/trunk/src/orxonox/tools/Timer.cc
===================================================================
--- code/trunk/src/orxonox/tools/Timer.cc	(revision 1407)
+++ code/trunk/src/orxonox/tools/Timer.cc	(revision 1502)
@@ -27,4 +27,6 @@
  */
 
+#include <set>
+
 #include "OrxonoxStableHeaders.h"
 #include "Timer.h"
@@ -37,5 +39,8 @@
 namespace orxonox
 {
-    ConsoleCommandShortcutExtern(delay, AccessLevel::None);
+    SetConsoleCommandShortcutExtern(delay);
+    SetConsoleCommandShortcutExtern(killdelays);
+
+    static std::set<StaticTimer*> delaytimerset;
 
     /**
@@ -47,4 +52,6 @@
     {
         StaticTimer *delaytimer = new StaticTimer();
+        delaytimerset.insert(delaytimer);
+
         ExecutorStatic* delayexecutor = createExecutor(createFunctor(&executeDelayedCommand));
         delayexecutor->setDefaultValues(delaytimer, command);
@@ -61,4 +68,16 @@
         CommandExecutor::execute(command);
         delete timer;
+        delaytimerset.erase(timer);
+    }
+
+    /**
+        @brief Kills all delayed commands.
+    */
+    void killdelays()
+    {
+        for (std::set<StaticTimer*>::iterator it = delaytimerset.begin(); it != delaytimerset.end(); ++it)
+            delete (*it);
+
+        delaytimerset.clear();
     }
 
Index: code/trunk/src/orxonox/tools/Timer.h
===================================================================
--- code/trunk/src/orxonox/tools/Timer.h	(revision 1407)
+++ code/trunk/src/orxonox/tools/Timer.h	(revision 1502)
@@ -69,4 +69,5 @@
     class StaticTimer;
     void delay(float delay, const std::string& command);
+    void killdelays();
     void executeDelayedCommand(StaticTimer* timer, const std::string& command);
 
Index: code/trunk/src/util/Convert.h
===================================================================
--- code/trunk/src/util/Convert.h	(revision 1407)
+++ code/trunk/src/util/Convert.h	(revision 1502)
@@ -384,4 +384,6 @@
         else if (input.getType() == MT_vector3)
             return ConvertValue(output, input.getVector3());
+        else if (input.getType() == MT_vector4)
+            return ConvertValue(output, input.getVector4());
         else if (input.getType() == MT_quaternion)
             return ConvertValue(output, input.getQuaternion());
Index: code/trunk/src/util/Math.h
===================================================================
--- code/trunk/src/util/Math.h	(revision 1407)
+++ code/trunk/src/util/Math.h	(revision 1502)
@@ -121,4 +121,13 @@
 
 template <typename T>
+inline int mod(T x, int max)
+{
+    if (x >= 0)
+        return (x % max);
+    else
+        return ((x % max) + max);
+}
+
+template <typename T>
 T interpolate(float time, const T& start, const T& end)
 {
Index: code/trunk/src/util/MultiType.h
===================================================================
--- code/trunk/src/util/MultiType.h	(revision 1407)
+++ code/trunk/src/util/MultiType.h	(revision 1502)
@@ -54,4 +54,5 @@
     MT_vector2,
     MT_vector3,
+    MT_vector4,
     MT_colourvalue,
     MT_quaternion,
Index: code/trunk/src/util/MultiTypeMath.cc
===================================================================
--- code/trunk/src/util/MultiTypeMath.cc	(revision 1407)
+++ code/trunk/src/util/MultiTypeMath.cc	(revision 1502)
@@ -37,4 +37,6 @@
     else if (type == MT_vector3)
         this->vector3_ = orxonox::Vector3(0, 0, 0);
+    else if (type == MT_vector4)
+        this->vector4_ = orxonox::Vector4(0, 0, 0, 0);
     else if (type == MT_colourvalue)
         this->colourvalue_ = orxonox::ColourValue(0, 0, 0, 0);
@@ -55,4 +57,6 @@
         else if (this->type_ == MT_vector3)
             return (this->vector3_ == mtm.vector3_);
+        else if (this->type_ == MT_vector4)
+            return (this->vector4_ == mtm.vector4_);
         else if (this->type_ == MT_colourvalue)
             return (this->colourvalue_ == mtm.colourvalue_);
@@ -68,4 +72,14 @@
 }
 
+bool MultiTypeMath::operator==(const MultiTypeString& mts) const
+{
+    return MultiTypeString::operator==(mts);
+}
+
+bool MultiTypeMath::operator==(const MultiTypePrimitive& mtp) const
+{
+    return MultiTypePrimitive::operator==(mtp);
+}
+
 bool MultiTypeMath::operator!=(const MultiTypeMath& mtm) const
 {
@@ -76,4 +90,6 @@
         else if (this->type_ == MT_vector3)
             return (this->vector3_ != mtm.vector3_);
+        else if (this->type_ == MT_vector4)
+            return (this->vector4_ != mtm.vector4_);
         else if (this->type_ == MT_colourvalue)
             return (this->colourvalue_ != mtm.colourvalue_);
@@ -87,4 +103,14 @@
 
     return true;
+}
+
+bool MultiTypeMath::operator!=(const MultiTypeString& mts) const
+{
+    return MultiTypeString::operator!=(mts);
+}
+
+bool MultiTypeMath::operator!=(const MultiTypePrimitive& mtp) const
+{
+    return MultiTypePrimitive::operator!=(mtp);
 }
 
@@ -123,4 +149,6 @@
 MultiTypeMath::operator orxonox::Vector3() const
 { return (this->type_ == MT_vector3) ? this->vector3_ : getConvertedValue<MultiTypeMath, orxonox::Vector3>(*this); }
+MultiTypeMath::operator orxonox::Vector4() const
+{ return (this->type_ == MT_vector4) ? this->vector4_ : getConvertedValue<MultiTypeMath, orxonox::Vector4>(*this); }
 MultiTypeMath::operator orxonox::Quaternion() const
 { return (this->type_ == MT_quaternion) ? this->quaternion_ : getConvertedValue<MultiTypeMath, orxonox::Quaternion>(*this); }
@@ -137,4 +165,5 @@
     this->vector2_ = mtm.vector2_;
     this->vector3_ = mtm.vector3_;
+    this->vector4_ = mtm.vector4_;
     this->quaternion_ = mtm.quaternion_;
     this->colourvalue_ = mtm.colourvalue_;
@@ -143,4 +172,14 @@
 }
 
+void MultiTypeMath::setValue(const MultiTypeString& mts)
+{
+    MultiTypeString::setValue(mts);
+}
+
+void MultiTypeMath::setValue(const MultiTypePrimitive& mtp)
+{
+    MultiTypePrimitive::setValue(mtp);
+}
+
 std::string MultiTypeMath::getTypename() const
 {
@@ -149,4 +188,6 @@
     else if (this->type_ == MT_vector3)
         return "Vector3";
+    else if (this->type_ == MT_vector4)
+        return "Vector4";
     else if (this->type_ == MT_colourvalue)
         return "ColourValue";
@@ -169,4 +210,6 @@
     else if (this->type_ == MT_vector3)
         ConvertValue(&output, this->vector3_);
+    else if (this->type_ == MT_vector4)
+        ConvertValue(&output, this->vector4_);
     else if (this->type_ == MT_colourvalue)
         ConvertValue(&output, this->colourvalue_);
@@ -189,4 +232,6 @@
     else if (this->type_ == MT_vector3)
         return ConvertValue(&this->vector3_, value, orxonox::Vector3(0, 0, 0));
+    else if (this->type_ == MT_vector4)
+        return ConvertValue(&this->vector4_, value, orxonox::Vector4(0, 0, 0, 0));
     else if (this->type_ == MT_colourvalue)
         return ConvertValue(&this->colourvalue_, value, orxonox::ColourValue(0, 0, 0, 0));
@@ -201,4 +246,54 @@
 }
 
+bool MultiTypeMath::assimilate(const MultiTypeMath& mtm, const MultiTypeMath& defvalue)
+{
+    if (this->type_ == MT_void)
+        return ConvertValue(&this->value_.void_, mtm, defvalue.value_.void_);
+    else if (this->type_ == MT_int)
+        return ConvertValue(&this->value_.int_, mtm, defvalue.value_.int_);
+    else if (this->type_ == MT_uint)
+        return ConvertValue(&this->value_.uint_, mtm, defvalue.value_.uint_);
+    else if (this->type_ == MT_char)
+        return ConvertValue(&this->value_.char_, mtm, defvalue.value_.char_);
+    else if (this->type_ == MT_uchar)
+        return ConvertValue(&this->value_.uchar_, mtm, defvalue.value_.uchar_);
+    else if (this->type_ == MT_short)
+        return ConvertValue(&this->value_.short_, mtm, defvalue.value_.short_);
+    else if (this->type_ == MT_ushort)
+        return ConvertValue(&this->value_.ushort_, mtm, defvalue.value_.ushort_);
+    else if (this->type_ == MT_long)
+        return ConvertValue(&this->value_.long_, mtm, defvalue.value_.long_);
+    else if (this->type_ == MT_ulong)
+        return ConvertValue(&this->value_.ulong_, mtm, defvalue.value_.ulong_);
+    else if (this->type_ == MT_float)
+        return ConvertValue(&this->value_.float_, mtm, defvalue.value_.float_);
+    else if (this->type_ == MT_double)
+        return ConvertValue(&this->value_.double_, mtm, defvalue.value_.double_);
+    else if (this->type_ == MT_longdouble)
+        return ConvertValue(&this->value_.longdouble_, mtm, defvalue.value_.longdouble_);
+    else if (this->type_ == MT_bool)
+        return ConvertValue(&this->value_.bool_, mtm, defvalue.value_.bool_);
+    else if (this->type_ == MT_constchar)
+        return ConvertValue(&this->string_, mtm, defvalue.string_);
+    else if (this->type_ == MT_string)
+        return ConvertValue(&this->string_, mtm, defvalue.string_);
+    else if (this->type_ == MT_vector2)
+        return ConvertValue(&this->vector2_, mtm, defvalue.vector2_);
+    else if (this->type_ == MT_vector3)
+        return ConvertValue(&this->vector3_, mtm, defvalue.vector3_);
+    else if (this->type_ == MT_vector4)
+        return ConvertValue(&this->vector4_, mtm, defvalue.vector4_);
+    else if (this->type_ == MT_colourvalue)
+        return ConvertValue(&this->colourvalue_, mtm, defvalue.colourvalue_);
+    else if (this->type_ == MT_quaternion)
+        return ConvertValue(&this->quaternion_, mtm, defvalue.quaternion_);
+    else if (this->type_ == MT_radian)
+        return ConvertValue(&this->radian_, mtm, defvalue.radian_);
+    else if (this->type_ == MT_degree)
+        return ConvertValue(&this->degree_, mtm, defvalue.degree_);
+    else
+        return false;
+}
+
 std::ostream& operator<<(std::ostream& out, MultiTypeMath& mtm)
 {
Index: code/trunk/src/util/MultiTypeMath.h
===================================================================
--- code/trunk/src/util/MultiTypeMath.h	(revision 1407)
+++ code/trunk/src/util/MultiTypeMath.h	(revision 1502)
@@ -63,4 +63,5 @@
         inline MultiTypeMath(const orxonox::Vector2&     value) { this->setValue(value); }
         inline MultiTypeMath(const orxonox::Vector3&     value) { this->setValue(value); }
+        inline MultiTypeMath(const orxonox::Vector4&     value) { this->setValue(value); }
         inline MultiTypeMath(const orxonox::ColourValue& value) { this->setValue(value); }
         inline MultiTypeMath(const orxonox::Quaternion&  value) { this->setValue(value); }
@@ -68,4 +69,6 @@
         inline MultiTypeMath(const orxonox::Degree&      value) { this->setValue(value); }
         inline MultiTypeMath(const MultiTypeMath& mtm)          { this->setValue(mtm);   }
+        inline MultiTypeMath(const MultiTypeString& mts)        { this->setValue(mts);   }
+        inline MultiTypeMath(const MultiTypePrimitive& mtp)     { this->setValue(mtp);   }
         virtual inline ~MultiTypeMath() {}
 
@@ -73,4 +76,5 @@
         inline MultiTypeMath& operator=(const orxonox::Vector2&     value) { this->setValue(value); return *this; }
         inline MultiTypeMath& operator=(const orxonox::Vector3&     value) { this->setValue(value); return *this; }
+        inline MultiTypeMath& operator=(const orxonox::Vector4&     value) { this->setValue(value); return *this; }
         inline MultiTypeMath& operator=(const orxonox::ColourValue& value) { this->setValue(value); return *this; }
         inline MultiTypeMath& operator=(const orxonox::Quaternion&  value) { this->setValue(value); return *this; }
@@ -78,8 +82,11 @@
         inline MultiTypeMath& operator=(const orxonox::Degree&      value) { this->setValue(value); return *this; }
         inline MultiTypeMath& operator=(const MultiTypeMath& mtm)          { this->setValue(mtm);   return *this; }
+        inline MultiTypeMath& operator=(const MultiTypeString& mts)        { this->setValue(mts);   return *this; }
+        inline MultiTypeMath& operator=(const MultiTypePrimitive mtp)      { this->setValue(mtp);   return *this; }
 
         using MultiTypeString::operator==;
         inline bool operator==(const orxonox::Vector2&     value) const { return (this->vector2_     == value); }
         inline bool operator==(const orxonox::Vector3&     value) const { return (this->vector3_     == value); }
+        inline bool operator==(const orxonox::Vector4&     value) const { return (this->vector4_     == value); }
         inline bool operator==(const orxonox::ColourValue& value) const { return (this->colourvalue_ == value); }
         inline bool operator==(const orxonox::Quaternion&  value) const { return (this->quaternion_  == value); }
@@ -87,8 +94,11 @@
         inline bool operator==(const orxonox::Degree&      value) const { return (this->degree_      == value); }
         bool operator==(const MultiTypeMath& mtm) const;
+        bool operator==(const MultiTypeString& mts) const;
+        bool operator==(const MultiTypePrimitive& mtp) const;
 
         using MultiTypeString::operator!=;
         inline bool operator!=(const orxonox::Vector2&     value) const { return (this->vector2_     != value); }
         inline bool operator!=(const orxonox::Vector3&     value) const { return (this->vector3_     != value); }
+        inline bool operator!=(const orxonox::Vector4&     value) const { return (this->vector4_     != value); }
         inline bool operator!=(const orxonox::ColourValue& value) const { return (this->colourvalue_ != value); }
         inline bool operator!=(const orxonox::Quaternion&  value) const { return (this->quaternion_  != value); }
@@ -96,4 +106,6 @@
         inline bool operator!=(const orxonox::Degree&      value) const { return (this->degree_      != value); }
         bool operator!=(const MultiTypeMath& mtm) const;
+        bool operator!=(const MultiTypeString& mts) const;
+        bool operator!=(const MultiTypePrimitive& mtp) const;
 
         virtual operator void*()                const;
@@ -114,4 +126,5 @@
         virtual operator orxonox::Vector2()     const;
         virtual operator orxonox::Vector3()     const;
+        virtual operator orxonox::Vector4()     const;
         virtual operator orxonox::ColourValue() const;
         virtual operator orxonox::Quaternion()  const;
@@ -122,4 +135,5 @@
         inline void setValue(const orxonox::Vector2&     value) { this->type_ = MT_vector2;     this->vector2_     = value; }
         inline void setValue(const orxonox::Vector3&     value) { this->type_ = MT_vector3;     this->vector3_     = value; }
+        inline void setValue(const orxonox::Vector4&     value) { this->type_ = MT_vector4;     this->vector4_     = value; }
         inline void setValue(const orxonox::ColourValue& value) { this->type_ = MT_colourvalue; this->colourvalue_ = value; }
         inline void setValue(const orxonox::Quaternion&  value) { this->type_ = MT_quaternion;  this->quaternion_  = value; }
@@ -127,7 +141,10 @@
         inline void setValue(const orxonox::Degree&      value) { this->type_ = MT_degree;      this->degree_      = value; }
         void setValue(const MultiTypeMath& mtm);
+        void setValue(const MultiTypeString& mts);
+        void setValue(const MultiTypePrimitive& mtp);
 
         inline orxonox::Vector2     getVector2()     const { return this->vector2_;     }
         inline orxonox::Vector3     getVector3()     const { return this->vector3_;     }
+        inline orxonox::Vector4     getVector4()     const { return this->vector4_;     }
         inline orxonox::ColourValue getColourValue() const { return this->colourvalue_; }
         inline orxonox::Quaternion  getQuaternion()  const { return this->quaternion_;  }
@@ -137,4 +154,5 @@
         inline orxonox::Vector2&     getVector2()     { return this->vector2_;     }
         inline orxonox::Vector3&     getVector3()     { return this->vector3_;     }
+        inline orxonox::Vector4&     getVector4()     { return this->vector4_;     }
         inline orxonox::ColourValue& getColourValue() { return this->colourvalue_; }
         inline orxonox::Quaternion&  getQuaternion()  { return this->quaternion_;  }
@@ -145,4 +163,5 @@
         inline void getValue(orxonox::Vector2*     variable) const { (*variable) = orxonox::Vector2     (this->vector2_);     }
         inline void getValue(orxonox::Vector3*     variable) const { (*variable) = orxonox::Vector3     (this->vector3_);     }
+        inline void getValue(orxonox::Vector4*     variable) const { (*variable) = orxonox::Vector4     (this->vector4_);     }
         inline void getValue(orxonox::ColourValue* variable) const { (*variable) = orxonox::ColourValue (this->colourvalue_); }
         inline void getValue(orxonox::Quaternion*  variable) const { (*variable) = orxonox::Quaternion  (this->quaternion_);  }
@@ -155,7 +174,10 @@
         virtual bool fromString(const std::string value);
 
+        virtual bool assimilate(const MultiTypeMath& mtm, const MultiTypeMath& defvalue = MultiTypeMath());
+
     protected:
         orxonox::Vector2      vector2_;
         orxonox::Vector3      vector3_;
+        orxonox::Vector4      vector4_;
         orxonox::ColourValue  colourvalue_;
         orxonox::Quaternion   quaternion_;
Index: code/trunk/src/util/MultiTypePrimitive.cc
===================================================================
--- code/trunk/src/util/MultiTypePrimitive.cc	(revision 1407)
+++ code/trunk/src/util/MultiTypePrimitive.cc	(revision 1502)
@@ -266,4 +266,37 @@
 }
 
+bool MultiTypePrimitive::assimilate(const MultiTypePrimitive& mtp, const MultiTypePrimitive& defvalue)
+{
+    if (this->type_ == MT_void)
+        return ConvertValue(&this->value_.void_, mtp, defvalue.value_.void_);
+    else if (this->type_ == MT_int)
+        return ConvertValue(&this->value_.int_, mtp, defvalue.value_.int_);
+    else if (this->type_ == MT_uint)
+        return ConvertValue(&this->value_.uint_, mtp, defvalue.value_.uint_);
+    else if (this->type_ == MT_char)
+        return ConvertValue(&this->value_.char_, mtp, defvalue.value_.char_);
+    else if (this->type_ == MT_uchar)
+        return ConvertValue(&this->value_.uchar_, mtp, defvalue.value_.uchar_);
+    else if (this->type_ == MT_short)
+        return ConvertValue(&this->value_.short_, mtp, defvalue.value_.short_);
+    else if (this->type_ == MT_ushort)
+        return ConvertValue(&this->value_.ushort_, mtp, defvalue.value_.ushort_);
+    else if (this->type_ == MT_long)
+        return ConvertValue(&this->value_.long_, mtp, defvalue.value_.long_);
+    else if (this->type_ == MT_ulong)
+        return ConvertValue(&this->value_.ulong_, mtp, defvalue.value_.ulong_);
+    else if (this->type_ == MT_float)
+        return ConvertValue(&this->value_.float_, mtp, defvalue.value_.float_);
+    else if (this->type_ == MT_double)
+        return ConvertValue(&this->value_.double_, mtp, defvalue.value_.double_);
+    else if (this->type_ == MT_longdouble)
+        return ConvertValue(&this->value_.longdouble_, mtp, defvalue.value_.longdouble_);
+    else if (this->type_ == MT_bool)
+        return ConvertValue(&this->value_.bool_, mtp, defvalue.value_.bool_);
+    else
+        return false;
+
+}
+
 std::ostream& operator<<(std::ostream& out, const MultiTypePrimitive& mtp)
 {
Index: code/trunk/src/util/MultiTypePrimitive.h
===================================================================
--- code/trunk/src/util/MultiTypePrimitive.h	(revision 1407)
+++ code/trunk/src/util/MultiTypePrimitive.h	(revision 1502)
@@ -138,5 +138,5 @@
         void setValue(const MultiTypePrimitive& mtp);
 
-        inline void*          getVoid()          const { return this->value_.void_;        }
+        inline void*          getVoid()          const { return this->value_.void_;       }
         inline int            getInt()           const { return this->value_.int_;        }
         inline unsigned int   getUnsignedInt()   const { return this->value_.uint_;       }
@@ -187,4 +187,6 @@
         virtual bool fromString(const std::string value);
 
+        virtual bool assimilate(const MultiTypePrimitive& mtp, const MultiTypePrimitive& defvalue = MultiTypePrimitive());
+
     protected:
         MultiTypeValue  value_;
Index: code/trunk/src/util/MultiTypeString.cc
===================================================================
--- code/trunk/src/util/MultiTypeString.cc	(revision 1407)
+++ code/trunk/src/util/MultiTypeString.cc	(revision 1502)
@@ -33,5 +33,5 @@
 MultiTypeString::MultiTypeString(MultiType type) : MultiTypePrimitive(type)
 {
-    // Nothing to do for string and xml-element
+    // Nothing to do for string
 }
 
@@ -49,4 +49,9 @@
 }
 
+bool MultiTypeString::operator==(const MultiTypePrimitive& mtp) const
+{
+    return MultiTypePrimitive::operator==(mtp);
+}
+
 bool MultiTypeString::operator!=(const MultiTypeString& mts) const
 {
@@ -60,4 +65,9 @@
 
     return true;
+}
+
+bool MultiTypeString::operator!=(const MultiTypePrimitive& mtp) const
+{
+    return MultiTypePrimitive::operator!=(mtp);
 }
 
@@ -99,4 +109,9 @@
 }
 
+void MultiTypeString::setValue(const MultiTypePrimitive& mtp)
+{
+    MultiTypePrimitive::setValue(mtp);
+}
+
 std::string MultiTypeString::getTypename() const
 {
@@ -136,4 +151,40 @@
 }
 
+bool MultiTypeString::assimilate(const MultiTypeString& mts, const MultiTypeString& defvalue)
+{
+    if (this->type_ == MT_void)
+        return ConvertValue(&this->value_.void_, mts, defvalue.value_.void_);
+    else if (this->type_ == MT_int)
+        return ConvertValue(&this->value_.int_, mts, defvalue.value_.int_);
+    else if (this->type_ == MT_uint)
+        return ConvertValue(&this->value_.uint_, mts, defvalue.value_.uint_);
+    else if (this->type_ == MT_char)
+        return ConvertValue(&this->value_.char_, mts, defvalue.value_.char_);
+    else if (this->type_ == MT_uchar)
+        return ConvertValue(&this->value_.uchar_, mts, defvalue.value_.uchar_);
+    else if (this->type_ == MT_short)
+        return ConvertValue(&this->value_.short_, mts, defvalue.value_.short_);
+    else if (this->type_ == MT_ushort)
+        return ConvertValue(&this->value_.ushort_, mts, defvalue.value_.ushort_);
+    else if (this->type_ == MT_long)
+        return ConvertValue(&this->value_.long_, mts, defvalue.value_.long_);
+    else if (this->type_ == MT_ulong)
+        return ConvertValue(&this->value_.ulong_, mts, defvalue.value_.ulong_);
+    else if (this->type_ == MT_float)
+        return ConvertValue(&this->value_.float_, mts, defvalue.value_.float_);
+    else if (this->type_ == MT_double)
+        return ConvertValue(&this->value_.double_, mts, defvalue.value_.double_);
+    else if (this->type_ == MT_longdouble)
+        return ConvertValue(&this->value_.longdouble_, mts, defvalue.value_.longdouble_);
+    else if (this->type_ == MT_bool)
+        return ConvertValue(&this->value_.bool_, mts, defvalue.value_.bool_);
+    else if (this->type_ == MT_constchar)
+        return ConvertValue(&this->string_, mts, defvalue.string_);
+    else if (this->type_ == MT_string)
+        return ConvertValue(&this->string_, mts, defvalue.string_);
+    else
+        return false;
+}
+
 std::ostream& operator<<(std::ostream& out, MultiTypeString& mts)
 {
Index: code/trunk/src/util/MultiTypeString.h
===================================================================
--- code/trunk/src/util/MultiTypeString.h	(revision 1407)
+++ code/trunk/src/util/MultiTypeString.h	(revision 1502)
@@ -61,54 +61,59 @@
         inline MultiTypeString(long double    value) : MultiTypePrimitive(value) {}
         inline MultiTypeString(bool           value) : MultiTypePrimitive(value) {}
-        inline MultiTypeString(const char*           value)   { this->setValue(value); }
-        inline MultiTypeString(const std::string&    value)   { this->setValue(value); }
-        inline MultiTypeString(const MultiTypeString& mts)    { this->setValue(mts);   }
+        inline MultiTypeString(const char*             value) { this->setValue(value); }
+        inline MultiTypeString(const std::string&      value) { this->setValue(value); }
+        inline MultiTypeString(const MultiTypeString&    mts)  { this->setValue(mts);   }
+        inline MultiTypeString(const MultiTypePrimitive& mtp)  { this->setValue(mtp);   }
         virtual inline ~MultiTypeString() {}
 
         using MultiTypePrimitive::operator=;
-        inline MultiTypeString& operator=(const char*             value)   { this->setValue(value); return *this; }
-        inline MultiTypeString& operator=(const std::string&      value)   { this->setValue(value); return *this; }
-        inline MultiTypeString& operator=(const MultiTypeString& mts)      { this->setValue(mts);   return *this; }
+        inline MultiTypeString& operator=(const char*             value) { this->setValue(value); return *this; }
+        inline MultiTypeString& operator=(const std::string&      value) { this->setValue(value); return *this; }
+        inline MultiTypeString& operator=(const MultiTypeString&    mts) { this->setValue(mts);   return *this; }
+        inline MultiTypeString& operator=(const MultiTypePrimitive& mtp) { this->setValue(mtp);   return *this; }
 
         using MultiTypePrimitive::operator==;
-        inline bool operator==(const char*             value) const { return (this->string_      == std::string(value)); }
-        inline bool operator==(const std::string&      value) const { return (this->string_      == value);              }
-        bool operator==(const MultiTypeString& mts) const;
+        inline bool operator==(const char*        value) const { return (this->string_ == std::string(value)); }
+        inline bool operator==(const std::string& value) const { return (this->string_ == value);              }
+        bool operator==(const MultiTypeString&    mts) const;
+        bool operator==(const MultiTypePrimitive& mtp) const;
 
         using MultiTypePrimitive::operator!=;
-        inline bool operator!=(const char*             value) const { return (this->string_      != std::string(value)); }
-        inline bool operator!=(const std::string&      value) const { return (this->string_      != value);              }
-        bool operator!=(const MultiTypeString& mts) const;
+        inline bool operator!=(const char*        value) const { return (this->string_ != std::string(value)); }
+        inline bool operator!=(const std::string& value) const { return (this->string_ != value);              }
+        bool operator!=(const MultiTypeString&    mts) const;
+        bool operator!=(const MultiTypePrimitive& mtp) const;
 
-        virtual operator void*()                const;
-        virtual operator int()                  const;
-        virtual operator unsigned int()         const;
-        virtual operator char()                 const;
-        virtual operator unsigned char()        const;
-        virtual operator short()                const;
-        virtual operator unsigned short()       const;
-        virtual operator long()                 const;
-        virtual operator unsigned long()        const;
-        virtual operator float ()               const;
-        virtual operator double ()              const;
-        virtual operator long double()          const;
-        virtual operator bool()                 const;
-        virtual operator std::string()          const;
-        virtual operator const char*()          const;
+        virtual operator void*()          const;
+        virtual operator int()            const;
+        virtual operator unsigned int()   const;
+        virtual operator char()           const;
+        virtual operator unsigned char()  const;
+        virtual operator short()          const;
+        virtual operator unsigned short() const;
+        virtual operator long()           const;
+        virtual operator unsigned long()  const;
+        virtual operator float ()         const;
+        virtual operator double ()        const;
+        virtual operator long double()    const;
+        virtual operator bool()           const;
+        virtual operator std::string()    const;
+        virtual operator const char*()    const;
 
         using MultiTypePrimitive::setValue;
-        inline void setValue(const char*             value) { this->type_ = MT_string;     this->string_     = std::string(value); }
-        inline void setValue(const std::string&      value) { this->type_ = MT_string;     this->string_     = value;              }
-        void setValue(const MultiTypeString& mts);
+        inline void setValue(const char*        value) { this->type_ = MT_string; this->string_ = std::string(value); }
+        inline void setValue(const std::string& value) { this->type_ = MT_string; this->string_ = value;              }
+        void setValue(const MultiTypeString&    mts);
+        void setValue(const MultiTypePrimitive& mtp);
 
-        inline std::string getString()          const { return this->string_;         }
-        inline const char*  getConstChar()      const { return this->string_.c_str(); }
+        inline std::string getString()     const { return this->string_;         }
+        inline const char*  getConstChar() const { return this->string_.c_str(); }
 
-        inline std::string& getString()          { return this->string_;         }
-        inline const char*  getConstChar()       { return this->string_.c_str(); }
+        inline std::string& getString()    { return this->string_;         }
+        inline const char*  getConstChar() { return this->string_.c_str(); }
 
         using MultiTypePrimitive::getValue;
-        inline void getValue(std::string*      variable) const { (*variable) = this->string_;         }
-        inline void getValue(const char**      variable) const { (*variable) = this->string_.c_str(); }
+        inline void getValue(std::string* variable) const { (*variable) = this->string_;         }
+        inline void getValue(const char** variable) const { (*variable) = this->string_.c_str(); }
 
         virtual std::string getTypename() const;
@@ -116,4 +121,6 @@
         virtual std::string toString() const;
         virtual bool fromString(const std::string value);
+
+        virtual bool assimilate(const MultiTypeString& mts, const MultiTypeString& defvalue = MultiTypeString());
 
     protected:
Index: code/trunk/src/util/OrxonoxPlatform.h
===================================================================
--- code/trunk/src/util/OrxonoxPlatform.h	(revision 1502)
+++ code/trunk/src/util/OrxonoxPlatform.h	(revision 1502)
@@ -0,0 +1,282 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   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:
+ *      Reto Grieder
+ *
+ */
+
+/**
+ @file
+ @brief Various constants for compiler, architecture and platform. It's a mere
+        copy of the file found in the Ogre source code (OgrePlatform.h).
+ */
+
+#ifndef _OrxonoxPlatform_H__
+#define _OrxonoxPlatform_H__
+
+/* Initial platform/compiler-related stuff to set.
+*/
+#define ORXONOX_PLATFORM_WIN32 1
+#define ORXONOX_PLATFORM_LINUX 2
+#define ORXONOX_PLATFORM_APPLE 3
+
+#define ORXONOX_COMPILER_MSVC 1
+#define ORXONOX_COMPILER_GNUC 2
+#define ORXONOX_COMPILER_BORL 3
+
+#define ORXONOX_ENDIAN_LITTLE 1
+#define ORXONOX_ENDIAN_BIG 2
+
+#define ORXONOX_ARCHITECTURE_32 1
+#define ORXONOX_ARCHITECTURE_64 2
+
+/* Finds the compiler type and version.
+*/
+#if defined( _MSC_VER )
+#  define ORXONOX_COMPILER ORXONOX_COMPILER_MSVC
+#  define ORXONOX_COMP_VER _MSC_VER
+
+#elif defined( __GNUC__ )
+#  define ORXONOX_COMPILER ORXONOX_COMPILER_GNUC
+#  define ORXONOX_COMP_VER (((__GNUC__)*100) + \
+        (__GNUC_MINOR__*10) + \
+        __GNUC_PATCHLEVEL__)
+
+#elif defined( __BORLANDC__ )
+#  define ORXONOX_COMPILER ORXONOX_COMPILER_BORL
+#  define ORXONOX_COMP_VER __BCPLUSPLUS__
+
+#else
+#  pragma error "No known compiler. Abort! Abort!"
+
+#endif
+
+/* See if we can use __forceinline or if we need to use __inline instead */
+#if ORXONOX_COMPILER == ORXONOX_COMPILER_MSVC
+#  if ORXONOX_COMP_VER >= 1200
+#    define FORCEINLINE __forceinline
+#  endif
+#elif defined(__MINGW32__)
+#  if !defined(FORCEINLINE)
+#    define FORCEINLINE __inline
+#  endif
+#else
+#  define FORCEINLINE __inline
+#endif
+
+/* Finds the current platform */
+
+#if defined( __WIN32__ ) || defined( _WIN32 )
+#  define ORXONOX_PLATFORM ORXONOX_PLATFORM_WIN32
+
+#elif defined( __APPLE_CC__)
+#  define ORXONOX_PLATFORM ORXONOX_PLATFORM_APPLE
+
+#else
+#  define ORXONOX_PLATFORM ORXONOX_PLATFORM_LINUX
+#endif
+
+    /* Find the arch type */
+#if defined(__x86_64__) || defined(_M_X64) || defined(__powerpc64__) || defined(__alpha__) || defined(__ia64__) || defined(__s390__) || defined(__s390x__)
+#  define ORXONOX_ARCH_TYPE ORXONOX_ARCHITECTURE_64
+#else
+#  define ORXONOX_ARCH_TYPE ORXONOX_ARCHITECTURE_32
+#endif
+
+// For generating compiler warnings - should work on any compiler
+// As a side note, if you start your message with 'Warning: ', the MSVC
+// IDE actually does catch a warning :)
+// FIXME: Try this on linux box. Doesn't work with msvc
+//#define ORXONOX_QUOTE_INPLACE(x) # x
+//#define ORXONOX_QUOTE(x) ORXONOX_QUOTE_INPLACE(x)
+//#define ORXONOX_WARN( x )  message( __FILE__ "(" QUOTE( __LINE__ ) ") : " x "\n" )
+
+//----------------------------------------------------------------------------
+// Windows Settings
+#if ORXONOX_PLATFORM == ORXONOX_PLATFORM_WIN32
+
+// Win32 compilers use _DEBUG for specifying debug builds.
+#  ifdef _DEBUG
+#    define ORXONOX_DEBUG_MODE 1
+#  else
+#    define ORXONOX_DEBUG_MODE 0
+#  endif
+
+// Disable unicode support on MingW at the moment, poorly supported in stdlibc++
+// STLPORT fixes this though so allow if found
+// MinGW C++ Toolkit supports unicode and sets the define __MINGW32_TOOLKIT_UNICODE__ in _mingw.h
+#  if defined( __MINGW32__ ) && !defined(_STLPORT_VERSION)
+#    include<_mingw.h>
+#    if defined(__MINGW32_TOOLBOX_UNICODE__)
+#      define ORXONOX_UNICODE_SUPPORT 1
+#    else
+#      define ORXONOX_UNICODE_SUPPORT 0
+#    endif
+#  else
+#    define ORXONOX_UNICODE_SUPPORT 1
+#  endif
+
+#endif /* Platform Win32 */
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+// Linux/Apple Settings
+#if ORXONOX_PLATFORM == ORXONOX_PLATFORM_LINUX || ORXONOX_PLATFORM == ORXONOX_PLATFORM_APPLE
+
+
+// A quick define to overcome different names for the same function
+#  define stricmp strcasecmp
+
+// Unlike the Win32 compilers, Linux compilers seem to use DEBUG for when
+// specifying a debug build.
+// (??? this is wrong, on Linux debug builds aren't marked in any way unless
+// you mark it yourself any way you like it -- zap ???)
+#  ifdef DEBUG
+#    define ORXONOX_DEBUG_MODE 1
+#  else
+#    define ORXONOX_DEBUG_MODE 0
+#  endif
+
+/* FIXME: Check what this actually is and whether we need it or not
+#  if ORXONOX_PLATFORM == ORXONOX_PLATFORM_APPLE
+#    define ORXONOX_PLATFORM_LIB "OrxonoxPlatform.bundle"
+#  else
+// ORXONOX_PLATFORM_LINUX
+#    define ORXONOX_PLATFORM_LIB "libOrxonoxPlatform.so"
+#  endif
+*/
+
+// Always enable unicode support for the moment
+// Perhaps disable in old versions of gcc if necessary
+#  define ORXONOX_UNICODE_SUPPORT 1
+
+#endif /* Patform Linux/Apple */
+
+//For apple, we always have a custom config.h file
+#if ORXONOX_PLATFORM == ORXONOX_PLATFORM_APPLE
+#  include "config.h"
+#endif
+
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+// Endian Settings
+// check for BIG_ENDIAN config flag, set ORXONOX_ENDIAN correctly
+#ifdef ORXONOX_CONFIG_BIG_ENDIAN
+#  define ORXONOX_ENDIAN ORXONOX_ENDIAN_BIG
+#else
+#  define ORXONOX_ENDIAN ORXONOX_ENDIAN_LITTLE
+#endif
+
+//-----------------------------------------------------------------------
+// fixed width integers
+//-----------------------------------------------------------------------
+#if ORXONOX_COMPILER == 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;
+#else
+# include "inttypes.h"
+#endif
+
+namespace orxonox {
+#ifdef ORXONOX_DOUBLE_PRECISION
+typedef double Real;
+#else
+typedef float Real;
+#endif
+}
+
+
+#if ORXONOX_COMPILER == ORXONOX_COMPILER_MSVC
+// Turn off warnings generated by long std templates
+// This warns about truncation to 255 characters in debug/browse info
+//#   pragma warning (disable : 4786)
+
+// Turn off warnings generated by long std templates
+// This warns about truncation to 255 characters in debug/browse info
+//#   pragma warning (disable : 4503)
+
+// disable: conversion from 'double' to 'float', possible loss of data
+// disable: conversion from 'ogg_int64_t' to 'long', possible loss of data
+// This has been dealt with in base_properties of the solution since the
+// warning primarily occurs in library header files (which are mostly
+// included before OrxonoxPlatform.h is)
+//#   pragma warning (disable : 4244)
+
+// disable: "conversion from 'size_t' to 'unsigned int', possible loss of data
+//#   pragma warning (disable : 4267)
+
+// disable: "truncation from 'double' to 'float'
+//#   pragma warning (disable : 4305)
+
+// set to level 4: "<type> needs to have dll-interface to be used by clients'
+// Happens on STL member variables which are not public therefore is ok
+#   pragma warning (disable : 4251)
+
+// disable: 'MultiTypeString' : multiple assignment operators specified
+// Used in MultiType and works fine so far
+//#   pragma warning (disable : 4522)
+
+// disable: "non dll-interface class used as base for dll-interface class"
+// Happens when deriving from Singleton because bug in compiler ignores
+// template export
+//#   pragma warning (disable : 4275)
+
+// disable: "C++ Exception Specification ignored"
+// This is because MSVC 6 did not implement all the C++ exception
+// specifications in the ANSI C++ draft.
+//#   pragma warning( disable : 4290 )
+
+// disable: "no suitable definition provided for explicit template
+// instantiation request" Occurs in VC7 for no justifiable reason on all
+// #includes of Singleton
+//#   pragma warning( disable: 4661)
+
+// disable: deprecation warnings when using CRT calls in VC8
+// These show up on all C runtime lib code in VC8, disable since they clutter
+// the warnings with things we may not be able to do anything about (e.g.
+// generated code from nvparse etc). I doubt very much that these calls
+// will ever be actually removed from VC anyway, it would break too much code.
+//#	pragma warning( disable: 4996)
+
+// disable: "conditional expression constant", always occurs on
+// ORXONOX_MUTEX_CONDITIONAL when no threading enabled
+//#   pragma warning (disable : 201)
+
+
+// Define the english written operators like and, or, xor
+#include <iso646.h>
+
+#endif /* ORXONOX_COMPILER == ORXONOX_COMPILER_MSVC */
+
+// include visual leak detector to search for memory leaks
+//#include <vld.h>
+
+#endif /* _OrxonoxPlatform_H__ */
Index: code/trunk/src/util/String.cc
===================================================================
--- code/trunk/src/util/String.cc	(revision 1407)
+++ code/trunk/src/util/String.cc	(revision 1502)
@@ -108,6 +108,6 @@
 
     unsigned int quotecount = 0;
-    unsigned int quote = 0;
-    while ((quote = getNextQuote(str, quote)) < pos)
+    unsigned int quote = (unsigned int)-1;
+    while ((quote = getNextQuote(str, quote + 1)) < pos)
     {
         quotecount++;
@@ -185,4 +185,19 @@
     else
         return str;
+}
+
+/**
+    @brief Removes enclosing {braces}.
+    @param str The string to strip
+    @return The striped string
+*/
+std::string stripEnclosingBraces(const std::string& str)
+{
+    std::string output = str;
+
+    while (output.size() >= 2 && output[0] == '{' && output[output.size() - 1] == '}')
+        output = output.substr(1, output.size() - 2);
+
+    return output;
 }
 
Index: code/trunk/src/util/String.h
===================================================================
--- code/trunk/src/util/String.h	(revision 1407)
+++ code/trunk/src/util/String.h	(revision 1502)
@@ -47,4 +47,5 @@
 
 _UtilExport std::string  stripEnclosingQuotes(const std::string& str);
+_UtilExport std::string  stripEnclosingBraces(const std::string& str);
 
 _UtilExport bool         isEmpty(const std::string& str);
Index: code/trunk/src/util/UtilPrereqs.h
===================================================================
--- code/trunk/src/util/UtilPrereqs.h	(revision 1407)
+++ code/trunk/src/util/UtilPrereqs.h	(revision 1502)
@@ -35,5 +35,5 @@
 #define _UtilPrereqs_H__
 
-#include "OrxonoxPlatform.h"
+#include "util/OrxonoxPlatform.h"
 
 //-----------------------------------------------------------------------
