Index: /code/branches/console/src/core/ArgumentCompletionFunctions.cc
===================================================================
--- /code/branches/console/src/core/ArgumentCompletionFunctions.cc	(revision 1390)
+++ /code/branches/console/src/core/ArgumentCompletionFunctions.cc	(revision 1390)
@@ -0,0 +1,41 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if 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 "ArgumentCompletionFunctions.h"
+
+namespace orxonox
+{
+    namespace autocompletion
+    {
+        const std::list<std::pair<std::string, std::string> >& fallback()
+        {
+            static std::list<std::pair<std::string, std::string> > list;
+            return list;
+        }
+    }
+}
Index: /code/branches/console/src/core/ArgumentCompletionFunctions.h
===================================================================
--- /code/branches/console/src/core/ArgumentCompletionFunctions.h	(revision 1390)
+++ /code/branches/console/src/core/ArgumentCompletionFunctions.h	(revision 1390)
@@ -0,0 +1,43 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _ArgumentCompletionFunctions_H__
+#define _ArgumentCompletionFunctions_H__
+
+#include <list>
+#include <string>
+
+namespace orxonox
+{
+    namespace autocompletion
+    {
+        const std::list<std::pair<std::string, std::string> >& fallback();
+    }
+}
+
+#endif /* _ArgumentCompletionFunctions_H__ */
Index: /code/branches/console/src/core/CMakeLists.txt
===================================================================
--- /code/branches/console/src/core/CMakeLists.txt	(revision 1389)
+++ /code/branches/console/src/core/CMakeLists.txt	(revision 1390)
@@ -20,4 +20,6 @@
   CommandExecutor.cc
   CommandEvaluation.cc
+  ConsoleCommand.cc
+  ArgumentCompletionFunctions.cc
   ConsoleCommandCompilation.cc
   Language.cc
Index: /code/branches/console/src/core/CommandEvaluation.cc
===================================================================
--- /code/branches/console/src/core/CommandEvaluation.cc	(revision 1389)
+++ /code/branches/console/src/core/CommandEvaluation.cc	(revision 1390)
@@ -52,5 +52,5 @@
         this->bEvaluatedParams_ = false;
 
-        this->listOfPossibleFunctionClasses_.clear();
+        this->listOfPossibleIdentifiers_.clear();
         this->listOfPossibleFunctions_.clear();
 
@@ -64,16 +64,5 @@
     bool CommandEvaluation::isValid() const
     {
-        if (this->state_ == CS_Shortcut_Params || this->state_ == CS_Shortcut_Finished)
-        {
-            return this->function_;
-        }
-        else if (this->state_ == CS_Function_Params || this->state_ == CS_Function_Finished)
-        {
-            return (this->functionclass_ && this->function_);
-        }
-        else
-        {
-            return false;
-        }
+        return (this->function_);
     }
 
@@ -94,7 +83,7 @@
         unsigned int startindex = this->getStartindex();
         if (this->originalCommandTokens_.size() > startindex)
-            return evaluation.shortcut_->parse(removeSlashes(this->originalCommandTokens_.subSet(startindex).join() + evaluation.getAdditionalParameter()));
+            return this->function_->parse(removeSlashes(this->originalCommandTokens_.subSet(startindex).join() + this->getAdditionalParameter()));
         else
-            return evaluation.shortcut_->parse(removeSlashes(evaluation.additionalParameter_));
+            return this->function_->parse(removeSlashes(this->additionalParameter_));
     }
 
@@ -103,24 +92,33 @@
         switch (this->state_)
         {
+            case CS_Uninitialized:
             case CS_Empty:
-                std::list<std::pair<const std::string*, const std::string*> > temp;
-                if (evaluation.state_ == CS_Empty)
-                {
-                    temp.insert(temp.end(), this->listOfPossibleFunctions_.begin(), this->listOfPossibleFunctions_.end());
-                    temp.insert(temp.end(), this->listOfPossibleFunctionClasses_.begin(), this->listOfPossibleFunctionClasses_.end());
-                }
-                return (CommandEvaluation::getCommonBegin(temp));
+            case CS_ShortcutOrIdentifier:
+                {
+                    std::list<std::pair<const std::string*, const std::string*> > temp;
+                    if (this->state_ == CS_Empty)
+                    {
+                        temp.insert(temp.end(), this->listOfPossibleFunctions_.begin(), this->listOfPossibleFunctions_.end());
+                        temp.insert(temp.end(), this->listOfPossibleIdentifiers_.begin(), this->listOfPossibleIdentifiers_.end());
+                    }
+                    return (CommandEvaluation::getCommonBegin(temp));
+                }
                 break;
             case CS_Shortcut_Params:
                 if (this->function_)
-                    return (this->function_->getName() + " ");
+                {
+                    if (this->commandTokens_.size() > 1)
+                        return (this->function_->getName() + " " + this->commandTokens_.subSet(1, this->commandTokens_.size() - 1).join() + " " + CommandEvaluation::getCommonBegin(this->listOfPossibleArguments_));
+                    else
+                        return (this->function_->getName() + " ");
+                }
                 break;
             case CS_Shortcut_Finished:
                 if (this->function_)
                 {
-                    if (this->function_->getParamCount() == 0)
+                    if (this->commandTokens_.size() > 1)
+                        return (this->function_->getName() + " " + this->originalCommandTokens_.subSet(1, this->originalCommandTokens_.size() - 1).join());
+                    else
                         return (this->function_->getName());
-                    else if (this->originalCommandTokens_.size() > 1)
-                        return (this->function_->getName() + " " + this->originalCommandTokens_.subSet(1).join());
                 }
                 break;
@@ -131,14 +129,21 @@
             case CS_Function_Params:
                 if (this->functionclass_ && this->function_)
-                    return (this->functionclass_->getName() + " " + this->function_->getName() + " ");
+                {
+                    if (this->commandTokens_.size() > 2)
+                        return (this->functionclass_->getName() + " " + this->function_->getName() + " " + this->commandTokens_.subSet(2, this->commandTokens_.size() - 1).join() + " " + CommandEvaluation::getCommonBegin(this->listOfPossibleArguments_));
+                    else
+                        return (this->functionclass_->getName() + " " + this->function_->getName() + " ");
+                }
                 break;
             case CS_Function_Finished:
                 if (this->functionclass_ && this->function_)
                 {
-                    if (this->function_->getParamCount() == 0)
-                        return (this->functionclass_->getName() + " " + this->unction_->getName());
-                    else if (this->originalCommandTokens_.size() > 2)
-                        return (this->functionclass_->getName() + " " + this->function_->getName() + " " + this->originalCommandTokens_.subSet(2).join());
-                }
+                    if (this->commandTokens_.size() > 2)
+                        return (this->functionclass_->getName() + " " + this->function_->getName() + " " + this->originalCommandTokens_.subSet(2, this->originalCommandTokens_.size() - 1).join());
+                    else
+                        return (this->functionclass_->getName() + " " + this->function_->getName());
+                }
+               break;
+            case CS_Error:
                 break;
         }
@@ -151,6 +156,9 @@
         switch (this->state_)
         {
+            case CS_Uninitialized:
+                break;
             case CS_Empty:
-                return (CommandEvaluation::dump(this->listOfPossibleFunctions_) + "\n" + CommandExecutor::dump(this->listOfPossibleFunctionClasses_));
+            case CS_ShortcutOrIdentifier:
+                return (CommandEvaluation::dump(this->listOfPossibleFunctions_) + "\n" + CommandEvaluation::dump(this->listOfPossibleIdentifiers_));
                 break;
             case CS_Function:
@@ -158,6 +166,7 @@
                 break;
             case CS_Shortcut_Params:
+            case CS_Function_Params:
+                return CommandEvaluation::dump(this->listOfPossibleArguments_);
             case CS_Shortcut_Finished:
-            case CS_Function_Params:
             case CS_Function_Finished:
                 if (this->function_)
@@ -175,5 +184,4 @@
     {
         this->bEvaluatedParams_ = false;
-        this->evaluatedExecutor_ = 0;
 
         for (unsigned int i = 0; i < MAX_FUNCTOR_ARGUMENTS; i++)
@@ -188,16 +196,10 @@
         {
             if (this->function_->evaluate(this->getAdditionalParameter(), this->param_, " "))
-            {
                 this->bEvaluatedParams_ = true;
-                this->evaluatedExecutor_ = this->function_;
-            }
         }
         else if (this->originalCommandTokens_.size() > startindex)
         {
             if (this->function_->evaluate(this->originalCommandTokens_.subSet(startindex).join() + this->getAdditionalParameter(), this->param_, " "))
-            {
                 this->bEvaluatedParams_ = true;
-                this->evaluatedExecutor_ = this->function_;
-            }
         }
     }
@@ -238,5 +240,5 @@
         if (this->state_ == CS_Shortcut_Params || this->state_ == CS_Shortcut_Finished)
             return 1;
-        else if (this->state_ == CS_Function_Params || this->state_ == CS_Function_Finished)
+        else if (this->state_ == CS_Function || this->state_ == CS_Function_Params || this->state_ == CS_Function_Finished)
             return 2;
         else
Index: /code/branches/console/src/core/CommandEvaluation.h
===================================================================
--- /code/branches/console/src/core/CommandEvaluation.h	(revision 1389)
+++ /code/branches/console/src/core/CommandEvaluation.h	(revision 1390)
@@ -44,5 +44,5 @@
         CS_Uninitialized,
         CS_Empty,
-        CS_FunctionClass_Or_Shortcut,
+        CS_ShortcutOrIdentifier,
         CS_Shortcut_Params,
         CS_Shortcut_Finished,
@@ -60,5 +60,5 @@
             void initialize(const std::string& command);
 
-            void execute() const;
+            bool execute() const;
             std::string complete() const;
             std::string hint() const;
@@ -101,8 +101,10 @@
                 { this->bNewCommand_ = bNewCommand; }
 
-            inline std::list<std::pair<const std::string*, const std::string*> >& getListOfPossibleFunctionClasses()
-                { return this->listOfPossibleFunctionClasses_; }
+            inline std::list<std::pair<const std::string*, const std::string*> >& getListOfPossibleIdentifiers()
+                { return this->listOfPossibleIdentifiers_; }
             inline std::list<std::pair<const std::string*, const std::string*> >& getListOfPossibleFunctions()
                 { return this->listOfPossibleFunctions_; }
+            inline std::list<std::pair<const std::string*, const std::string*> >& getListOfPossibleArguments()
+                { return this->listOfPossibleArguments_; }
 
             inline void setAdditionalParameter(const std::string& param)
@@ -132,6 +134,7 @@
             std::string additionalParameter_;
 
-            std::list<std::pair<const std::string*, const std::string*> > listOfPossibleFunctionClasses_;
+            std::list<std::pair<const std::string*, const std::string*> > listOfPossibleIdentifiers_;
             std::list<std::pair<const std::string*, const std::string*> > listOfPossibleFunctions_;
+            std::list<std::pair<const std::string*, const std::string*> > listOfPossibleArguments_;
 
             Identifier* functionclass_;
Index: /code/branches/console/src/core/CommandExecutor.cc
===================================================================
--- /code/branches/console/src/core/CommandExecutor.cc	(revision 1389)
+++ /code/branches/console/src/core/CommandExecutor.cc	(revision 1390)
@@ -56,4 +56,11 @@
     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;
@@ -135,10 +142,179 @@
         switch (CommandExecutor::getEvaluation().getState())
         {
-        }
-    }
-
-    bool CommandExecutor::argumentsFinished(unsigned int num)
-    {
-        return (CommandExecutor::argumentsFinished() >= num);
+            case CS_Uninitialized:
+                // Impossible
+                break;
+            case CS_Empty:
+                CommandExecutor::createListOfPossibleIdentifiers(CommandExecutor::getArgument(0));
+                CommandExecutor::createListOfPossibleFunctions(CommandExecutor::getArgument(0));
+
+                if (CommandExecutor::argumentsGiven() > 0)
+                {
+                    CommandExecutor::getEvaluation().setState(CS_ShortcutOrIdentifier);
+                    CommandExecutor::parse(command, false);
+                    return;
+                }
+                break;
+            case CS_ShortcutOrIdentifier:
+                if (CommandExecutor::argumentsFinished() > 0 || !CommandExecutor::getEvaluation().isNewCommand())
+                {
+                    // There's already a finished first argument - check if it's function or a classname
+                    CommandExecutor::getEvaluation().setIdentifier(CommandExecutor::getPossibleIdentifier(CommandExecutor::getArgument(0)));
+                    CommandExecutor::getEvaluation().setFunction(CommandExecutor::getPossibleCommand(CommandExecutor::getArgument(0)));
+
+                    if (CommandExecutor::getEvaluation().getFunction())
+                    {
+                        // It's a shortcut - continue parsing
+                        CommandExecutor::getEvaluation().setState(CS_Shortcut_Params);
+                        if (CommandExecutor::argumentsFinished() > 0 )
+                            CommandExecutor::parse(command, false);
+                        else
+                            CommandExecutor::parse(command + " ", false);
+                        return;
+                    }
+                    else if (CommandExecutor::getEvaluation().getIdentifier())
+                    {
+                        // It's a classname - continue parsing
+                        CommandExecutor::getEvaluation().setState(CS_Function);
+                        if (CommandExecutor::argumentsFinished() > 0 )
+                            CommandExecutor::parse(command, false);
+                        else
+                            CommandExecutor::parse(command + " ", false);
+                        return;
+                    }
+                }
+
+                if (CommandExecutor::argumentsFinished() == 0)
+                {
+                    // There is no finished first argument
+                    unsigned int numIdentifiers = CommandExecutor::getEvaluation().getListOfPossibleIdentifiers().size();
+                    unsigned int numCommands = CommandExecutor::getEvaluation().getListOfPossibleFunctions().size();
+
+                    if (numCommands == 1 && numIdentifiers == 0)
+                    {
+                        // It must be this command
+                        const std::string* possibleCommand = (*CommandExecutor::getEvaluation().getListOfPossibleFunctions().begin()).second;
+                        CommandExecutor::getEvaluation().setState(CS_Shortcut_Params);
+                        CommandExecutor::getEvaluation().setFunction(CommandExecutor::getPossibleCommand(*possibleCommand));
+                        CommandExecutor::parse(*possibleCommand + " ", false);
+                        return;
+                    }
+                    else if (numIdentifiers == 1 && numCommands == 0)
+                    {
+                        // It must be this classname
+                        const std::string* possibleIdentifier = (*CommandExecutor::getEvaluation().getListOfPossibleIdentifiers().begin()).second;
+                        CommandExecutor::getEvaluation().setState(CS_Function);
+                        CommandExecutor::getEvaluation().setIdentifier(CommandExecutor::getPossibleIdentifier(*possibleIdentifier));
+                        CommandExecutor::parse(*possibleIdentifier + " ", false);
+                        return;
+                    }
+                }
+
+                // It's not a shortcut nor a classname
+                CommandExecutor::getEvaluation().setState(CS_Error);
+                AddLanguageEntry("commandexecutorunknownfirstargument", "is not a shortcut nor a classname");
+                CommandExecutor::getEvaluation().setError("Error: " + CommandExecutor::getArgument(0) + " " + GetLocalisation("commandexecutorunknownfirstargument") + ".");
+                break;
+            case CS_Function:
+                if (CommandExecutor::getEvaluation().getIdentifier() && CommandExecutor::argumentsGiven() > 1)
+                {
+                    if (CommandExecutor::argumentsFinished() > 1 || !CommandExecutor::getEvaluation().isNewCommand())
+                    {
+                        // There is already a second argument - check if it's a valid function
+                        CommandExecutor::getEvaluation().setFunction(CommandExecutor::getPossibleCommand(CommandExecutor::getArgument(1), CommandExecutor::getEvaluation().getIdentifier()));
+
+                        if (CommandExecutor::getEvaluation().getFunction())
+                        {
+                            // It's a shortcut - continue parsing
+                            CommandExecutor::getEvaluation().setState(CS_Function_Params);
+                            if (CommandExecutor::argumentsFinished() > 1 )
+                                CommandExecutor::parse(command, false);
+                            else
+                                CommandExecutor::parse(command + " ", false);
+                            return;
+                        }
+                    }
+
+                    if (CommandExecutor::argumentsFinished() <= 1)
+                    {
+                        // There is no finished second argument
+                        CommandExecutor::createListOfPossibleFunctions(CommandExecutor::getArgument(0), CommandExecutor::getEvaluation().getIdentifier());
+                        unsigned int numFunctions = CommandExecutor::getEvaluation().getListOfPossibleFunctions().size();
+
+                        if (numFunctions == 1)
+                        {
+                            // It must be this command
+                            const std::string* possibleCommand = (*CommandExecutor::getEvaluation().getListOfPossibleFunctions().begin()).second;
+                            CommandExecutor::getEvaluation().setState(CS_Function_Params);
+                            CommandExecutor::getEvaluation().setFunction(CommandExecutor::getPossibleCommand(*possibleCommand));
+                            CommandExecutor::parse(*possibleCommand + " ", false);
+                            return;
+                        }
+                    }
+
+                    // It's not a function
+                    AddLanguageEntry("commandexecutorunknowncommand", "is not a valid commandname");
+                    CommandExecutor::getEvaluation().setError("Error: " + CommandExecutor::getArgument(1) + " " + GetLocalisation("commandexecutorunknowncommand") + ".");
+                }
+
+                // Bad state
+                CommandExecutor::getEvaluation().setState(CS_Error);
+                break;
+            case CS_Shortcut_Params:
+            case CS_Function_Params:
+                if (CommandExecutor::getEvaluation().getFunction())
+                {
+                    unsigned int startindex = 0;
+                    if (CommandExecutor::getEvaluation().getState() == CS_Shortcut_Params)
+                        startindex = 1;
+                    else if (CommandExecutor::getEvaluation().getState() == CS_Function_Params)
+                        startindex = 2;
+
+                    if (CommandExecutor::argumentsGiven() >= startindex)
+                    {
+                        if (CommandExecutor::enoughArgumentsGiven(CommandExecutor::getEvaluation().getFunction()))
+                        {
+                            if (CommandExecutor::getEvaluation().getState() == CS_Shortcut_Params)
+                                CommandExecutor::getEvaluation().setState(CS_Shortcut_Finished);
+                            else if (CommandExecutor::getEvaluation().getState() == CS_Function_Params)
+                                CommandExecutor::getEvaluation().setState(CS_Function_Finished);
+                            return;
+                        }
+                        else
+                        {
+                            CommandExecutor::createListOfPossibleArguments(CommandExecutor::getLastArgument(), CommandExecutor::getEvaluation().getFunction(), CommandExecutor::getEvaluation().getOriginalTokens().size() - startindex);
+                            unsigned int numArguments = CommandExecutor::getEvaluation().getListOfPossibleArguments().size();
+
+                            if (numArguments == 1)
+                            {
+                                // There is exactly one possible argument
+                                const std::string* possibleArgument = (*CommandExecutor::getEvaluation().getListOfPossibleArguments().begin()).second;
+                                CommandExecutor::parse(CommandExecutor::getEvaluation().getTokens().subSet(0, CommandExecutor::getEvaluation().getTokens().size() - 1 - startindex).join() + " " + (*possibleArgument) + " ");
+                                return;
+                            }
+
+                            if (!CommandExecutor::getEvaluation().isNewCommand())
+                            {
+                                // There is more than one argument, but the user wants to use this - check if there is a perfect match
+                                const std::string* possibleArgument = CommandExecutor::getPossibleArgument(CommandExecutor::getLastArgument(), CommandExecutor::getEvaluation().getFunction(), CommandExecutor::getEvaluation().getOriginalTokens().size() - startindex);
+                                if (possibleArgument)
+                                {
+                                    // There is such an argument - use it
+                                    CommandExecutor::parse(command + " ", false);
+                                    return;
+                                }
+                            }
+                        }
+                    }
+                }
+
+                // Bad state
+                CommandExecutor::getEvaluation().setState(CS_Error);
+                break;
+            case CS_Shortcut_Finished:
+            case CS_Function_Finished:
+            case CS_Error:
+                break;
+        }
     }
 
@@ -152,5 +328,18 @@
     }
 
-    std::string CommandExecutor::getToken(unsigned int index)
+    unsigned int CommandExecutor::argumentsGiven()
+    {
+        return CommandExecutor::getEvaluation().getOriginalTokens().size();
+    }
+
+    bool CommandExecutor::enoughArgumentsGiven(ConsoleCommand* command)
+    {
+        if (CommandExecutor::getEvaluation().getIdentifier())
+            return (CommandExecutor::argumentsGiven() >= (2 + command->getParamCount()));
+        else
+            return (CommandExecutor::argumentsGiven() >= (1 + command->getParamCount()));
+    }
+
+    std::string CommandExecutor::getArgument(unsigned int index)
     {
         if ((index >= 0) && index < (CommandExecutor::getEvaluation().getOriginalTokens().size()))
@@ -160,22 +349,20 @@
     }
 
-    unsigned int CommandExecutor::argumentsGiven()
-    {
-        return CommandExecutor::getEvaluation().getOriginalTokens().size();
-    }
-
-    bool CommandExecutor::enoughArgumentsGiven(ConsoleCommand* command, unsigned int head)
-    {
-        return (CommandExecutor::argumentsGiven() >= (head + command->getParamCount()));
-    }
-
-    void CommandExecutor::createListOfPossibleFunctionClasses(const std::string& fragment)
+    std::string CommandExecutor::getLastArgument()
+    {
+        if (CommandExecutor::getEvaluation().getOriginalTokens().size() > 0)
+            return CommandExecutor::getEvaluation().getOriginalTokens()[0];
+        else
+            return "";
+    }
+
+    void CommandExecutor::createListOfPossibleIdentifiers(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().getListOfPossibleFunctionClasses().push_back(std::pair<const std::string*, const std::string*>(&(*it).first, &(*it).second->getName()));
-
-        CommandExecutor::getEvaluation().getListOfPossibleFunctionClasses().sort(CommandExecutor::compareStringsInList);
+                    CommandExecutor::getEvaluation().getListOfPossibleIdentifiers().push_back(std::pair<const std::string*, const std::string*>(&(*it).first, &(*it).second->getName()));
+
+        CommandExecutor::getEvaluation().getListOfPossibleIdentifiers().sort(CommandExecutor::compareStringsInList);
     }
 
@@ -197,4 +384,14 @@
     }
 
+    void CommandExecutor::createListOfPossibleArguments(const std::string& fragment, ConsoleCommand* command, unsigned int param)
+    {
+        for (std::list<std::pair<std::string, std::string> >::const_iterator it = command->getArgumentCompletionListBegin(param); it != command->getArgumentCompletionListEnd(param); ++it)
+            if ((*it).first.find(getLowercase(fragment)) == 0 || fragment == "")
+                CommandExecutor::getEvaluation().getListOfPossibleArguments().push_back(std::pair<const std::string*, const std::string*>(&(*it).first, &(*it).second));
+
+        CommandExecutor::getEvaluation().getListOfPossibleIdentifiers().sort(CommandExecutor::compareStringsInList);
+
+    }
+
     Identifier* CommandExecutor::getPossibleIdentifier(const std::string& name)
     {
@@ -223,4 +420,14 @@
     }
 
+    const std::string* CommandExecutor::getPossibleArgument(const std::string& name, ConsoleCommand* command, unsigned int param)
+    {
+        std::string lowercasename = getLowercase(name);
+        for (std::list<std::pair<std::string, std::string> >::const_iterator it = command->getArgumentCompletionListBegin(param); it != command->getArgumentCompletionListEnd(param); ++it)
+            if ((*it).first == lowercasename)
+                return &(*it).second;
+
+        return 0;
+    }
+
     bool CommandExecutor::compareStringsInList(const std::pair<const std::string*, const std::string*>& first, const std::pair<const std::string*, const std::string*>& second)
     {
Index: /code/branches/console/src/core/CommandExecutor.h
===================================================================
--- /code/branches/console/src/core/CommandExecutor.h	(revision 1389)
+++ /code/branches/console/src/core/CommandExecutor.h	(revision 1390)
@@ -78,15 +78,17 @@
             static void parse(const std::string& command, bool bInitialize = true);
 
-            static bool argumentsFinished(unsigned int num);
             static unsigned int argumentsFinished();
             static unsigned int argumentsGiven();
-            static bool enoughArgumentsGiven(ConsoleCommand* command, unsigned int head);
-            static std::string getToken(unsigned int index);
+            static bool enoughArgumentsGiven(ConsoleCommand* command);
+            static std::string getArgument(unsigned int index);
+            static std::string getLastArgument();
 
-            static void createListOfPossibleFunctionClasses(const std::string& fragment);
+            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 Identifier* getPossibleIdentifier(const std::string& name);
             static ConsoleCommand* getPossibleCommand(const std::string& name, Identifier* identifier = 0);
+            static const std::string* getPossibleArgument(const std::string& name, ConsoleCommand* command, unsigned int param);
 
             static bool compareStringsInList(const std::pair<const std::string*, const std::string*>& first, const std::pair<const std::string*, const std::string*>& second);
Index: /code/branches/console/src/core/ConsoleCommand.cc
===================================================================
--- /code/branches/console/src/core/ConsoleCommand.cc	(revision 1390)
+++ /code/branches/console/src/core/ConsoleCommand.cc	(revision 1390)
@@ -0,0 +1,77 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "ConsoleCommand.h"
+
+namespace orxonox
+{
+    ConsoleCommand::ConsoleCommand(FunctorStatic* functor, const std::string& name) : ExecutorStatic(functor, name)
+    {
+        this->accessLevel_ = AccessLevel::None;
+        this->autocompletionFunction_[0] = &autocompletion::fallback;
+        this->autocompletionFunction_[1] = &autocompletion::fallback;
+        this->autocompletionFunction_[2] = &autocompletion::fallback;
+        this->autocompletionFunction_[3] = &autocompletion::fallback;
+        this->autocompletionFunction_[4] = &autocompletion::fallback;
+    }
+
+    ConsoleCommand& ConsoleCommand::setArgumentCompletionList(unsigned int param, const std::list<std::pair<std::string, std::string> >& (*function) (void))
+    {
+        if (param >= 0 && param < 5)
+            this->autocompletionFunction_[param] = function;
+        else
+        {
+            COUT(2) << "Warning: Couldn't add autocompletion-function for param " << param << ": index out of bound." << std::endl;
+        }
+        return (*this);
+    }
+
+    const std::list<std::pair<std::string, std::string> >& ConsoleCommand::getArgumentCompletionList(unsigned int param) const
+    {
+        if (param >= 0 && param < 5)
+            return (*this->autocompletionFunction_[param])();
+        else
+            return autocompletion::fallback();
+    }
+
+    std::list<std::pair<std::string, std::string> >::const_iterator ConsoleCommand::getArgumentCompletionListBegin(unsigned int param) const
+    {
+        if (param >= 0 && param < 5)
+            return (*this->autocompletionFunction_[param])().begin();
+        else
+            return autocompletion::fallback().begin();
+    }
+
+    std::list<std::pair<std::string, std::string> >::const_iterator ConsoleCommand::getArgumentCompletionListEnd(unsigned int param) const
+    {
+        if (param >= 0 && param < 5)
+            return (*this->autocompletionFunction_[param])().end();
+        else
+            return autocompletion::fallback().end();
+    }
+}
Index: /code/branches/console/src/core/ConsoleCommand.h
===================================================================
--- /code/branches/console/src/core/ConsoleCommand.h	(revision 1389)
+++ /code/branches/console/src/core/ConsoleCommand.h	(revision 1390)
@@ -36,4 +36,5 @@
 #include "Identifier.h"
 #include "CommandExecutor.h"
+#include "ArgumentCompletionFunctions.h"
 
 
@@ -73,5 +74,5 @@
     {
         public:
-            ConsoleCommand(FunctorStatic* functor, const std::string& name = "") : ExecutorStatic(functor, name), accessLevel_(AccessLevel::None) {}
+            ConsoleCommand(FunctorStatic* functor, const std::string& name = "");
 
             inline ConsoleCommand& setDescription(const std::string& description)
@@ -99,6 +100,13 @@
                 { return this->accessLevel_; }
 
+            ConsoleCommand& setArgumentCompletionList(unsigned int param, const std::list<std::pair<std::string, std::string> >& (*function) (void));
+
+            const std::list<std::pair<std::string, std::string> >& getArgumentCompletionList(unsigned int param) const;
+            std::list<std::pair<std::string, std::string> >::const_iterator getArgumentCompletionListBegin(unsigned int param) const;
+            std::list<std::pair<std::string, std::string> >::const_iterator getArgumentCompletionListEnd(unsigned int param) const;
+
         private:
             AccessLevel::Level accessLevel_;
+            const std::list<std::pair<std::string, std::string> >& (*autocompletionFunction_[5]) (void);
     };
 
Index: /code/branches/console/src/core/Identifier.cc
===================================================================
--- /code/branches/console/src/core/Identifier.cc	(revision 1389)
+++ /code/branches/console/src/core/Identifier.cc	(revision 1390)
@@ -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;
@@ -272,4 +278,10 @@
     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_[command->getName()] = command;
