Index: code/branches/core4/src/core/CorePrereqs.h
===================================================================
--- code/branches/core4/src/core/CorePrereqs.h	(revision 3239)
+++ code/branches/core4/src/core/CorePrereqs.h	(revision 3243)
@@ -165,4 +165,5 @@
     // game states
     class Game;
+    struct GameStateConstrParams;
     class GameState;
     struct GameStateTreeNode;
Index: code/branches/core4/src/core/Game.cc
===================================================================
--- code/branches/core4/src/core/Game.cc	(revision 3239)
+++ code/branches/core4/src/core/Game.cc	(revision 3243)
@@ -54,12 +54,7 @@
     using boost::weak_ptr;
 
-    std::map<std::string, GameState*> Game::allStates_s;
-    Game* Game::singletonRef_s = 0;
-
     static void stop_game()
         { Game::getInstance().stop(); }
     SetConsoleCommandShortcutExternAlias(stop_game, "exit");
-    // Add an empty gamestate that serves as internal root state
-    AddGameState(GameState, "emptyRootGameState");
 
     struct _CoreExport GameStateTreeNode
@@ -69,4 +64,7 @@
         std::vector<shared_ptr<GameStateTreeNode> > children_;
     };
+
+    std::map<std::string, Game::GameStateInfo> Game::gameStateDeclarations_s;
+    Game* Game::singletonRef_s = 0;
 
     /**
@@ -76,14 +74,16 @@
     Game::Game(int argc, char** argv)
     {
-        assert(singletonRef_s == 0);
+        if (singletonRef_s != 0)
+        {
+            COUT(0) << "Error: The Game singleton cannot be recreated! Shutting down." << std::endl;
+            abort();
+        }
         singletonRef_s = this;
 
         this->bAbort_ = false;
         bChangingState_ = false;
-        // The empty root state is ALWAYS loaded!
-        this->rootStateNode_ = shared_ptr<GameStateTreeNode>(new GameStateTreeNode());
-        this->rootStateNode_->state_ = getState("emptyRootGameState");
-        this->activeStateNode_ = this->rootStateNode_;
-        this->activeStates_.push_back(this->rootStateNode_->state_);
+
+        // Create an empty root state
+        declareGameState<GameState>("GameState", "emptyRootGameState", true, false);
 
         // reset statistics
@@ -98,7 +98,25 @@
         this->gameClock_ = new Clock();
 
+        // Create the Core
         this->core_ = new orxonox::Core();
         this->core_->initialise(argc, argv);
 
+        // After the core has been created, we can safely instantiate the GameStates
+        for (std::map<std::string, GameStateInfo>::const_iterator it = gameStateDeclarations_s.begin();
+            it != gameStateDeclarations_s.end(); ++it)
+        {
+            // Only create the states appropriate for the game mode
+            //if (GameMode::showsGraphics || !it->second.bGraphicsMode)
+            GameStateConstrParams params = { it->second.stateName, it->second.bIgnoreTickTime };
+            gameStates_[getLowercase(it->second.stateName)] = GameStateFactory::fabricate(it->second.className, params);
+        }
+
+        // The empty root state is ALWAYS loaded!
+        this->rootStateNode_ = shared_ptr<GameStateTreeNode>(new GameStateTreeNode());
+        this->rootStateNode_->state_ = getState("emptyRootGameState");
+        this->activeStateNode_ = this->rootStateNode_;
+        this->activeStates_.push_back(this->rootStateNode_->state_);
+
+        // Do this after Core creation!
         RegisterRootObject(Game);
         this->setConfigValues();
@@ -110,11 +128,17 @@
     Game::~Game()
     {
-        // Destroy pretty much everyhting left
+        // Destroy the GameStates (note that the nodes still point to them, but doesn't matter)
+        for (std::map<std::string, GameState*>::const_iterator it = gameStates_.begin();
+            it != gameStates_.end(); ++it)
+            delete it->second;
+
+        // Destroy the Core and with it almost everything
         delete this->core_;
-
         delete this->gameClock_;
 
-        assert(singletonRef_s);
-        singletonRef_s = 0;
+        // Also, take care of the GameStateFactories
+        GameStateFactory::destroyFactories();
+
+        // Don't assign singletonRef_s with NULL! Recreation is not supported
     }
 
@@ -165,5 +189,5 @@
 
             // STATISTICS
-            statisticsTickInfo tickInfo = {currentTime, 0};
+            StatisticsTickInfo tickInfo = {currentTime, 0};
             statisticsTickTimes_.push_back(tickInfo);
             this->periodTime_ += this->gameClock_->getDeltaTimeMicroseconds();
@@ -240,5 +264,5 @@
             if (this->periodTime_ > statisticsRefreshCycle_)
             {
-                std::list<statisticsTickInfo>::iterator it = this->statisticsTickTimes_.begin();
+                std::list<StatisticsTickInfo>::iterator it = this->statisticsTickTimes_.begin();
                 assert(it != this->statisticsTickTimes_.end());
                 int64_t lastTime = currentTime - this->statisticsAvgLength_;
@@ -356,6 +380,6 @@
     GameState* Game::getState(const std::string& name)
     {
-        std::map<std::string, GameState*>::const_iterator it = allStates_s.find(getLowercase(name));
-        if (it != allStates_s.end())
+        std::map<std::string, GameState*>::const_iterator it = gameStates_.find(getLowercase(name));
+        if (it != gameStates_.end())
             return it->second;
         else
@@ -448,22 +472,18 @@
     }
 
-    /*static*/ bool Game::addGameState(GameState* state)
-    {
-        std::map<std::string, GameState*>::const_iterator it = allStates_s.find(getLowercase(state->getName()));
-        if (it == allStates_s.end())
-            allStates_s[getLowercase(state->getName())] = state;
-        else
-            ThrowException(GameState, "Cannot add two GameStates with the same name to 'Game'.");
-
-        // just a required dummy return value
-        return true;
-    }
-
-    /*static*/ void Game::destroyStates()
-    {
-        // Delete all GameStates created by the macros
-        for (std::map<std::string, GameState*>::const_iterator it = allStates_s.begin(); it != allStates_s.end(); ++it)
+    std::map<std::string, Game::GameStateFactory*> Game::GameStateFactory::factories_s;
+
+    /*static*/ GameState* Game::GameStateFactory::fabricate(const std::string& className, const GameStateConstrParams& params)
+    {
+        std::map<std::string, GameStateFactory*>::const_iterator it = factories_s.find(className);
+        assert(it != factories_s.end());
+        return it->second->fabricate(params);
+    }
+
+    /*static*/ void Game::GameStateFactory::destroyFactories()
+    {
+        for (std::map<std::string, GameStateFactory*>::const_iterator it = factories_s.begin(); it != factories_s.end(); ++it)
             delete it->second;
-        allStates_s.clear();
+        factories_s.clear();
     }
 }
Index: code/branches/core4/src/core/Game.h
===================================================================
--- code/branches/core4/src/core/Game.h	(revision 3239)
+++ code/branches/core4/src/core/Game.h	(revision 3243)
@@ -46,4 +46,5 @@
 #include <boost/preprocessor/cat.hpp>
 
+#include "util/Debug.h"
 #include "OrxonoxClass.h"
 
@@ -53,6 +54,6 @@
     and every following paramter is a constructor argument (which is usually non existent)
 */
-#define AddGameState(classname, ...) \
-    static bool BOOST_PP_CAT(bGameStateDummy_##classname, __LINE__) = orxonox::Game::addGameState(new classname(__VA_ARGS__))
+#define DeclareGameState(className, stateName, bIgnoreTickTime, bGraphicsMode) \
+    static bool BOOST_PP_CAT(bGameStateDummy_##className, __LINE__) = orxonox::Game::declareGameState<className>(#className, stateName, bIgnoreTickTime, bGraphicsMode)
 
 // tolua_begin
@@ -91,6 +92,6 @@
         void addTickTime(uint32_t length);
 
-        static bool addGameState(GameState* state);
-        static void destroyStates();
+        template <class T>
+        static bool declareGameState(const std::string& className, const std::string& stateName, bool bIgnoreTickTime, bool bConsoleMode);
         static Game& getInstance() { assert(singletonRef_s); return *singletonRef_s; } //tolua_export
 
@@ -99,5 +100,34 @@
 
     private:
-        struct statisticsTickInfo
+        class _CoreExport GameStateFactory
+        {
+        public:
+            virtual ~GameStateFactory() { }
+            static GameState* fabricate(const std::string& className, const GameStateConstrParams& params);
+            template <class T>
+            static void createFactory(const std::string& className)
+                { factories_s[className] = new TemplateGameStateFactory<T>(); }
+            static void destroyFactories();
+        private:
+            virtual GameState* fabricate(const GameStateConstrParams& params) = 0;
+            static std::map<std::string, GameStateFactory*> factories_s;
+        };
+        template <class T>
+        class TemplateGameStateFactory : public GameStateFactory
+        {
+        public:
+            GameState* fabricate(const GameStateConstrParams& params)
+                { return new T(params); }
+        };
+
+        struct GameStateInfo
+        {
+            std::string stateName;
+            std::string className;
+            bool bIgnoreTickTime;
+            bool bGraphicsMode;
+        };
+
+        struct StatisticsTickInfo
         {
             uint64_t    tickTime;
@@ -110,5 +140,6 @@
         void unloadState(GameState* state);
 
-        std::vector<GameState*>         activeStates_;
+        std::map<std::string, GameState*>    gameStates_;
+        std::vector<GameState*>              activeStates_;
         boost::shared_ptr<GameStateTreeNode> rootStateNode_;
         boost::shared_ptr<GameStateTreeNode> activeStateNode_;
@@ -123,5 +154,5 @@
         // variables for time statistics
         uint64_t                        statisticsStartTime_;
-        std::list<statisticsTickInfo>   statisticsTickTimes_;
+        std::list<StatisticsTickInfo>   statisticsTickTimes_;
         uint32_t                        periodTime_;
         uint32_t                        periodTickTime_;
@@ -134,9 +165,33 @@
         std::string                     levelName_;
 
-        static std::map<std::string, GameState*> allStates_s;
+        static std::map<std::string, GameStateInfo> gameStateDeclarations_s;
         static Game* singletonRef_s;        //!< Pointer to the Singleton
-        // tolua_begin
-    };
-}
-//tolua_end
+    }; // tolua_export
+
+    template <class T>
+    /*static*/ bool Game::declareGameState(const std::string& className, const std::string& stateName, bool bIgnoreTickTime, bool bGraphicsMode)
+    {
+        std::map<std::string, GameStateInfo>::const_iterator it = gameStateDeclarations_s.find(getLowercase(stateName));
+        if (it == gameStateDeclarations_s.end())
+        {
+            GameStateInfo& info = gameStateDeclarations_s[getLowercase(stateName)];
+            info.stateName = stateName;
+            info.className = className;
+            info.bIgnoreTickTime = bIgnoreTickTime;
+            info.bGraphicsMode = bGraphicsMode;
+        }
+        else
+        {
+            COUT(0) << "Error: Cannot declare two GameStates with the same name." << std::endl;
+            COUT(0) << "       Ignoring second one ('" << stateName << "')." << std::endl;
+        }
+
+        // Create a factory to delay GameState creation
+        GameStateFactory::createFactory<T>(className);
+
+        // just a required dummy return value
+        return true;
+    }
+} // tolua_export
+
 #endif /* _Game_H__ */
Index: code/branches/core4/src/core/GameState.cc
===================================================================
--- code/branches/core4/src/core/GameState.cc	(revision 3239)
+++ code/branches/core4/src/core/GameState.cc	(revision 3243)
@@ -45,7 +45,7 @@
         Constructor only initialises variables and sets the name permanently.
     */
-    GameState::GameState(const std::string& name, bool ignoreTickTime)
-        : name_(name)
-        , bIgnoreTickTime_(ignoreTickTime)
+    GameState::GameState(const GameStateConstrParams& params)
+        : name_(params.name)
+        , bIgnoreTickTime_(params.bIgnoreTickTime)
         , parent_(0)
     {
Index: code/branches/core4/src/core/GameState.h
===================================================================
--- code/branches/core4/src/core/GameState.h	(revision 3239)
+++ code/branches/core4/src/core/GameState.h	(revision 3243)
@@ -45,4 +45,14 @@
     /**
     @brief
+        Helper class to group construction parameters for better genericity.
+    */
+    struct GameStateConstrParams
+    {
+        std::string name;
+        bool bIgnoreTickTime;
+    };
+
+    /**
+    @brief
         An implementation of a tree to manage game states.
         This leads to a certain hierarchy that is created at runtime.
@@ -77,5 +87,5 @@
 
     public:
-        GameState(const std::string& name, bool ignoreTicktime = false);
+        GameState(const GameStateConstrParams& params);
         virtual ~GameState();
 
Index: code/branches/core4/src/orxonox/Main.cc
===================================================================
--- code/branches/core4/src/orxonox/Main.cc	(revision 3239)
+++ code/branches/core4/src/orxonox/Main.cc	(revision 3243)
@@ -70,8 +70,5 @@
         orxonox.requestState("root");
         orxonox.run();
-
-        // destroy the GameStates created pre-mainly
-        orxonox::Game::destroyStates();
-    } // orxonox gets destroyed right here!
+    }
 
     // Clean up class hierarchy stuff (identifiers, xmlport, configvalue, consolecommand)
Index: code/branches/core4/src/orxonox/gamestates/GSClient.cc
===================================================================
--- code/branches/core4/src/orxonox/gamestates/GSClient.cc	(revision 3239)
+++ code/branches/core4/src/orxonox/gamestates/GSClient.cc	(revision 3243)
@@ -38,10 +38,10 @@
 namespace orxonox
 {
-    AddGameState(GSClient, "client");
+    DeclareGameState(GSClient, "client", false, true);
 
     SetCommandLineArgument(ip, "127.0.0.1").information("#.#.#.#");
 
-    GSClient::GSClient(const std::string& name)
-        : GameState(name)
+    GSClient::GSClient(const GameStateConstrParams& params)
+        : GameState(params)
         , client_(0)
     {
Index: code/branches/core4/src/orxonox/gamestates/GSClient.h
===================================================================
--- code/branches/core4/src/orxonox/gamestates/GSClient.h	(revision 3239)
+++ code/branches/core4/src/orxonox/gamestates/GSClient.h	(revision 3243)
@@ -40,5 +40,5 @@
     {
     public:
-        GSClient(const std::string& name);
+        GSClient(const GameStateConstrParams& params);
         ~GSClient();
 
Index: code/branches/core4/src/orxonox/gamestates/GSDedicated.cc
===================================================================
--- code/branches/core4/src/orxonox/gamestates/GSDedicated.cc	(revision 3239)
+++ code/branches/core4/src/orxonox/gamestates/GSDedicated.cc	(revision 3243)
@@ -51,10 +51,10 @@
     const unsigned int MAX_COMMAND_LENGTH = 255;
     
-    AddGameState(GSDedicated, "dedicated");
+    DeclareGameState(GSDedicated, "dedicated", false, false);
     
     termios* GSDedicated::originalTerminalSettings_;
 
-    GSDedicated::GSDedicated(const std::string& name)
-        : GameState(name)
+    GSDedicated::GSDedicated(const GameStateConstrParams& params)
+        : GameState(params)
         , server_(0)
         , timeSinceLastUpdate_(0)
Index: code/branches/core4/src/orxonox/gamestates/GSDedicated.h
===================================================================
--- code/branches/core4/src/orxonox/gamestates/GSDedicated.h	(revision 3239)
+++ code/branches/core4/src/orxonox/gamestates/GSDedicated.h	(revision 3243)
@@ -48,5 +48,5 @@
     {
     public:
-        GSDedicated(const std::string& name);
+        GSDedicated(const GameStateConstrParams& params);
         ~GSDedicated();
 
Index: code/branches/core4/src/orxonox/gamestates/GSGraphics.cc
===================================================================
--- code/branches/core4/src/orxonox/gamestates/GSGraphics.cc	(revision 3239)
+++ code/branches/core4/src/orxonox/gamestates/GSGraphics.cc	(revision 3243)
@@ -57,8 +57,8 @@
 namespace orxonox
 {
-    AddGameState(GSGraphics, "graphics", true);
-
-    GSGraphics::GSGraphics(const std::string& name, bool countTickTime)
-        : GameState(name, countTickTime)
+    DeclareGameState(GSGraphics, "graphics", true, true);
+
+    GSGraphics::GSGraphics(const GameStateConstrParams& params)
+        : GameState(params)
         , inputManager_(0)
         , console_(0)
Index: code/branches/core4/src/orxonox/gamestates/GSGraphics.h
===================================================================
--- code/branches/core4/src/orxonox/gamestates/GSGraphics.h	(revision 3239)
+++ code/branches/core4/src/orxonox/gamestates/GSGraphics.h	(revision 3243)
@@ -52,5 +52,5 @@
     {
     public:
-        GSGraphics(const std::string& name, bool countTickTime);
+        GSGraphics(const GameStateConstrParams& params);
         ~GSGraphics();
         void setConfigValues();
Index: code/branches/core4/src/orxonox/gamestates/GSIOConsole.cc
===================================================================
--- code/branches/core4/src/orxonox/gamestates/GSIOConsole.cc	(revision 3239)
+++ code/branches/core4/src/orxonox/gamestates/GSIOConsole.cc	(revision 3243)
@@ -36,8 +36,8 @@
 namespace orxonox
 {
-    AddGameState(GSIOConsole, "ioConsole");
+    DeclareGameState(GSIOConsole, "ioConsole", false, false);
 
-    GSIOConsole::GSIOConsole(const std::string& name)
-        : GameState(name)
+    GSIOConsole::GSIOConsole(const GameStateConstrParams& params)
+        : GameState(params)
     {
     }
Index: code/branches/core4/src/orxonox/gamestates/GSIOConsole.h
===================================================================
--- code/branches/core4/src/orxonox/gamestates/GSIOConsole.h	(revision 3239)
+++ code/branches/core4/src/orxonox/gamestates/GSIOConsole.h	(revision 3243)
@@ -38,5 +38,5 @@
     {
     public:
-        GSIOConsole(const std::string& name);
+        GSIOConsole(const GameStateConstrParams& params);
         ~GSIOConsole();
 
Index: code/branches/core4/src/orxonox/gamestates/GSLevel.cc
===================================================================
--- code/branches/core4/src/orxonox/gamestates/GSLevel.cc	(revision 3239)
+++ code/branches/core4/src/orxonox/gamestates/GSLevel.cc	(revision 3243)
@@ -56,5 +56,5 @@
 namespace orxonox
 {
-    AddGameState(GSLevel, "level");
+    DeclareGameState(GSLevel, "level", false, true);
 
     SetCommandLineArgument(level, "").shortcut("l");
@@ -63,6 +63,6 @@
     XMLFile* GSLevel::startFile_s = NULL;
 
-    GSLevel::GSLevel(const std::string& name)
-        : GameState(name)
+    GSLevel::GSLevel(const GameStateConstrParams& params)
+        : GameState(params)
         , keyBinder_(0)
         , gameInputState_(0)
Index: code/branches/core4/src/orxonox/gamestates/GSLevel.h
===================================================================
--- code/branches/core4/src/orxonox/gamestates/GSLevel.h	(revision 3239)
+++ code/branches/core4/src/orxonox/gamestates/GSLevel.h	(revision 3243)
@@ -41,5 +41,5 @@
     {
     public:
-        GSLevel(const std::string& name);
+        GSLevel(const GameStateConstrParams& params);
         ~GSLevel();
         void setConfigValues();
Index: code/branches/core4/src/orxonox/gamestates/GSMainMenu.cc
===================================================================
--- code/branches/core4/src/orxonox/gamestates/GSMainMenu.cc	(revision 3239)
+++ code/branches/core4/src/orxonox/gamestates/GSMainMenu.cc	(revision 3243)
@@ -43,8 +43,8 @@
 namespace orxonox
 {
-    AddGameState(GSMainMenu, "mainMenu");
+    DeclareGameState(GSMainMenu, "mainMenu", false, true);
 
-    GSMainMenu::GSMainMenu(const std::string& name)
-        : GameState(name)
+    GSMainMenu::GSMainMenu(const GameStateConstrParams& params)
+        : GameState(params)
         , inputState_(0)
     {
Index: code/branches/core4/src/orxonox/gamestates/GSMainMenu.h
===================================================================
--- code/branches/core4/src/orxonox/gamestates/GSMainMenu.h	(revision 3239)
+++ code/branches/core4/src/orxonox/gamestates/GSMainMenu.h	(revision 3243)
@@ -40,5 +40,5 @@
     {
     public:
-        GSMainMenu(const std::string& name);
+        GSMainMenu(const GameStateConstrParams& params);
         ~GSMainMenu();
 
Index: code/branches/core4/src/orxonox/gamestates/GSRoot.cc
===================================================================
--- code/branches/core4/src/orxonox/gamestates/GSRoot.cc	(revision 3239)
+++ code/branches/core4/src/orxonox/gamestates/GSRoot.cc	(revision 3243)
@@ -40,5 +40,5 @@
 namespace orxonox
 {
-    AddGameState(GSRoot, "root", true);
+    DeclareGameState(GSRoot, "root", true, false);
     SetCommandLineSwitch(console);
     // Shortcuts for easy direct loading
@@ -48,6 +48,6 @@
     SetCommandLineSwitch(standalone);
 
-    GSRoot::GSRoot(const std::string& name, bool countTickTime)
-        : GameState(name, countTickTime)
+    GSRoot::GSRoot(const GameStateConstrParams& params)
+        : GameState(params)
         , timeFactor_(1.0f)
         , bPaused_(false)
Index: code/branches/core4/src/orxonox/gamestates/GSRoot.h
===================================================================
--- code/branches/core4/src/orxonox/gamestates/GSRoot.h	(revision 3239)
+++ code/branches/core4/src/orxonox/gamestates/GSRoot.h	(revision 3243)
@@ -38,5 +38,5 @@
     {
     public:
-        GSRoot(const std::string& name, bool countTickTime);
+        GSRoot(const GameStateConstrParams& params);
         ~GSRoot();
 
Index: code/branches/core4/src/orxonox/gamestates/GSServer.cc
===================================================================
--- code/branches/core4/src/orxonox/gamestates/GSServer.cc	(revision 3239)
+++ code/branches/core4/src/orxonox/gamestates/GSServer.cc	(revision 3243)
@@ -37,10 +37,10 @@
 namespace orxonox
 {
-    AddGameState(GSServer, "server");
+    DeclareGameState(GSServer, "server", false, true);
 
     SetCommandLineArgument(port, 55556).shortcut("p").information("0-65535");
 
-    GSServer::GSServer(const std::string& name)
-        : GameState(name)
+    GSServer::GSServer(const GameStateConstrParams& params)
+        : GameState(params)
         , server_(0)
     {
Index: code/branches/core4/src/orxonox/gamestates/GSServer.h
===================================================================
--- code/branches/core4/src/orxonox/gamestates/GSServer.h	(revision 3239)
+++ code/branches/core4/src/orxonox/gamestates/GSServer.h	(revision 3243)
@@ -40,5 +40,5 @@
     {
     public:
-        GSServer(const std::string& name);
+        GSServer(const GameStateConstrParams& params);
         ~GSServer();
 
Index: code/branches/core4/src/orxonox/gamestates/GSStandalone.cc
===================================================================
--- code/branches/core4/src/orxonox/gamestates/GSStandalone.cc	(revision 3239)
+++ code/branches/core4/src/orxonox/gamestates/GSStandalone.cc	(revision 3243)
@@ -34,8 +34,8 @@
 namespace orxonox
 {
-    AddGameState(GSStandalone, "standalone");
+    DeclareGameState(GSStandalone, "standalone", false, true);
 
-    GSStandalone::GSStandalone(const std::string& name)
-        : GameState(name)
+    GSStandalone::GSStandalone(const GameStateConstrParams& params)
+        : GameState(params)
     {
     }
Index: code/branches/core4/src/orxonox/gamestates/GSStandalone.h
===================================================================
--- code/branches/core4/src/orxonox/gamestates/GSStandalone.h	(revision 3239)
+++ code/branches/core4/src/orxonox/gamestates/GSStandalone.h	(revision 3243)
@@ -38,5 +38,5 @@
     {
     public:
-        GSStandalone(const std::string& name);
+        GSStandalone(const GameStateConstrParams& params);
         ~GSStandalone();
 
