Index: /code/trunk/src/libraries/core/BaseObject.cc
===================================================================
--- /code/trunk/src/libraries/core/BaseObject.cc	(revision 6799)
+++ /code/trunk/src/libraries/core/BaseObject.cc	(revision 6800)
@@ -103,4 +103,11 @@
         }
     }
+    
+    /** @brief Adds an object which listens to the events of this object. */
+    void BaseObject::registerEventListener(BaseObject* object)
+    {
+        COUT(4) << "New EventListener: " << object->getIdentifier()->getName() << " &(" << object << ")." << std::endl;
+        this->eventListeners_.insert(object);
+    }
 
     /**
@@ -356,4 +363,6 @@
     {
         this->registerEventStates();
+        
+        COUT(4) << this->getIdentifier()->getName() << " (&" << this << ") processing event. originator: " << event.originator_->getIdentifier()->getName() << " (&" << event.originator_ << "), activate: " << event.activate_ << ", name: " << event.name_ << ", statename: " << event.statename_ << "." << std::endl;
 
         std::map<std::string, EventState*>::const_iterator it = this->eventStates_.find(event.statename_);
Index: /code/trunk/src/libraries/core/BaseObject.h
===================================================================
--- /code/trunk/src/libraries/core/BaseObject.h	(revision 6799)
+++ /code/trunk/src/libraries/core/BaseObject.h	(revision 6800)
@@ -188,6 +188,5 @@
         private:
             /** @brief Adds an object which listens to the events of this object. */
-            inline void registerEventListener(BaseObject* object)
-                { this->eventListeners_.insert(object); }
+            void registerEventListener(BaseObject* object);
             /** @brief Removes an event listener from this object. */
             inline void unregisterEventListener(BaseObject* object)
Index: /code/trunk/src/libraries/core/Event.cc
===================================================================
--- /code/trunk/src/libraries/core/Event.cc	(revision 6799)
+++ /code/trunk/src/libraries/core/Event.cc	(revision 6800)
@@ -59,16 +59,22 @@
         this->bProcessingEvent_ = true;
 
+        COUT(4) << "Processing event (EventState) : originator: " << event.originator_->getIdentifier()->getName() << " (&" << event.originator_ << "), activate: " << event.activate_ << ", name: " << event.name_ << ", statename: " << event.statename_ << ", object: " << object->getIdentifier()->getName() << " (&" << object << ")" << ", subclass: " << this->subclass_->getName() << ", (?): " << event.originator_->isA(this->subclass_) << "." << std::endl;
+        
         // check if the originator is an instance of the requested class
         if (event.originator_->isA(this->subclass_))
         {
+            // If the EventState doesn't act as an EventSink.
             // actualize the activationcounter
-            if (event.activate_)
-                ++this->activeEvents_;
-            else
+            if(!this->bSink_)
             {
-                --this->activeEvents_;
+                if (event.activate_)
+                    ++this->activeEvents_;
+                else
+                {
+                    --this->activeEvents_;
 
-                if (this->activeEvents_ < 0)
-                    this->activeEvents_ = 0;
+                    if (this->activeEvents_ < 0)
+                        this->activeEvents_ = 0;
+                }
             }
 
@@ -78,5 +84,5 @@
                 (*this->statefunction_)();
             }
-            else if ((this->activeEvents_ == 1 && event.activate_) || (this->activeEvents_ == 0 && !event.activate_))
+            else if (this->bSink_ || (!this->bSink_ && ((this->activeEvents_ == 1 && event.activate_) || (this->activeEvents_ == 0 && !event.activate_)) ) )
             {
                 // if the eventfunction needs a state, we just call the function if the state changed from 0 to 1 (state = true) or from 1 to 0 (state = false) [but not if activeEvents_ is > 1]
@@ -84,5 +90,5 @@
                 {
                     // one argument: just the eventstate
-                    (*this->statefunction_)(this->activeEvents_);
+                    (*this->statefunction_)(event.activate_);
                 }
                 else if (this->statefunction_->getParamCount() >= 2)
@@ -92,5 +98,5 @@
                     {
                         // if the subclass is BaseObject, we don't have to cast the pointer
-                        (*this->statefunction_)(this->activeEvents_, event.originator_);
+                        (*this->statefunction_)(event.activate_, event.originator_);
                     }
                     else
@@ -98,5 +104,5 @@
                         // else cast the pointer to the desired class
                         void* castedOriginator = event.originator_->getDerivedPointer(this->subclass_->getClassID());
-                        (*this->statefunction_)(this->activeEvents_, castedOriginator);
+                        (*this->statefunction_)(event.activate_, castedOriginator);
                     }
                 }
Index: /code/trunk/src/libraries/core/Event.h
===================================================================
--- /code/trunk/src/libraries/core/Event.h	(revision 6799)
+++ /code/trunk/src/libraries/core/Event.h	(revision 6800)
@@ -46,4 +46,5 @@
         BaseObject* originator_; //!< The object which triggered this event
         std::string name_;       //!< The name of this event
+
     };
 
@@ -66,5 +67,5 @@
     {
         public:
-            EventState(Functor* statefunction, Identifier* subclass) : bProcessingEvent_(false), activeEvents_(0), statefunction_(statefunction), subclass_(subclass) {}
+            EventState(Functor* statefunction, Identifier* subclass, bool bSink = false) : bProcessingEvent_(false), activeEvents_(0), statefunction_(statefunction), subclass_(subclass), bSink_(bSink) {}
             virtual ~EventState();
 
@@ -79,4 +80,5 @@
             Functor*    statefunction_;     //!< A functor to set the state
             Identifier* subclass_;          //!< Originators must be an instance of this class (usually BaseObject, but some statefunctions allow a second argument with an originator of a specific class)
+            bool        bSink_;             //!< Determines whether the EventState acts as an EventSink forwarding any Event (even if the state didn't change) or in the normal manner, only processing Events that change the state.
     };
 }
Index: /code/trunk/src/libraries/core/EventIncludes.h
===================================================================
--- /code/trunk/src/libraries/core/EventIncludes.h	(revision 6799)
+++ /code/trunk/src/libraries/core/EventIncludes.h	(revision 6800)
@@ -52,7 +52,17 @@
     } \
     XMLPortEventStateIntern(xmlportevent##function, classname, statename, xmlelement, mode)
+    
+#define XMLPortEventSink(classname, subclassname, statename, function, xmlelement, mode) \
+    orxonox::EventState* containername##function = this->getEventState(statename); \
+    if (!containername##function) \
+    { \
+        containername##function = new orxonox::EventState(orxonox::createFunctor(&classname::function, this), orxonox::ClassIdentifier<subclassname>::getIdentifier(), true); \
+        this->addEventState(statename, containername##function); \
+    } \
+    XMLPortEventStateIntern(xmlportevent##function, classname, statename, xmlelement, mode)
 
 /**
-    @brief Like XMLPortEventState but with additional template arguments to identify the function of the state (if ambiguous).
+    @brief Like XMLPortEventState but creates an event sink instead of an event state.
+           The most important destinction between an EventState and an EventSink is, that an EventState only processes event which change the state of the EventState, where as an EventSink is an EventState that processes any Event that reaches it.
 */
 #define XMLPortEventStateTemplate(classname, subclassname, statename, function, xmlelement, mode, ...) \
Index: /code/trunk/src/modules/objects/ObjectsPrereqs.h
===================================================================
--- /code/trunk/src/modules/objects/ObjectsPrereqs.h	(revision 6799)
+++ /code/trunk/src/modules/objects/ObjectsPrereqs.h	(revision 6800)
@@ -85,6 +85,9 @@
     // triggers
     class CheckPoint;
+    class DistanceMultiTrigger;
     class DistanceTrigger;
     class EventTrigger;
+    class MultiTrigger;
+    class MultiTriggerContainer;
     class Trigger;
 }
Index: /code/trunk/src/modules/objects/eventsystem/EventListener.cc
===================================================================
--- /code/trunk/src/modules/objects/eventsystem/EventListener.cc	(revision 6799)
+++ /code/trunk/src/modules/objects/eventsystem/EventListener.cc	(revision 6800)
@@ -61,4 +61,6 @@
             return;
         }
+        
+        COUT(4) << "EventListener: Processing event: originator: " << event.originator_->getIdentifier()->getName() << " (&" << event.originator_ << ")" << ", activate: " << event.activate_ << ", name: " << event.name_ << std::endl;
 
         this->bActive_ = true;
Index: /code/trunk/src/modules/objects/triggers/CMakeLists.txt
===================================================================
--- /code/trunk/src/modules/objects/triggers/CMakeLists.txt	(revision 6799)
+++ /code/trunk/src/modules/objects/triggers/CMakeLists.txt	(revision 6800)
@@ -1,6 +1,9 @@
 ADD_SOURCE_FILES(OBJECTS_SRC_FILES
-  Trigger.cc
+  CheckPoint.cc
+  DistanceMultiTrigger.cc
   DistanceTrigger.cc
   EventTrigger.cc
-  CheckPoint.cc
+  MultiTrigger.cc
+  MultiTriggerContainer.cc
+  Trigger.cc
 )
Index: /code/trunk/src/modules/objects/triggers/DistanceMultiTrigger.cc
===================================================================
--- /code/trunk/src/modules/objects/triggers/DistanceMultiTrigger.cc	(revision 6800)
+++ /code/trunk/src/modules/objects/triggers/DistanceMultiTrigger.cc	(revision 6800)
@@ -0,0 +1,109 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+*/
+
+#include "DistanceMultiTrigger.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+namespace orxonox
+{
+    
+    CreateFactory(DistanceMultiTrigger);
+    
+    DistanceMultiTrigger::DistanceMultiTrigger(BaseObject* creator) : MultiTrigger(creator)
+    {
+        RegisterObject(DistanceMultiTrigger);
+        
+        this->distance_ = 100.0f;
+    }
+    
+    DistanceMultiTrigger::~DistanceMultiTrigger()
+    {
+        
+    }
+    
+    void DistanceMultiTrigger::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(DistanceMultiTrigger, XMLPort, xmlelement, mode);
+
+        XMLPortParam(DistanceMultiTrigger, "distance", setDistance, getDistance, xmlelement, mode).defaultValues(100.0f);
+    }
+    
+    std::queue<MultiTriggerState*>* DistanceMultiTrigger::letTrigger(void)
+    {
+        ClassTreeMask targetMask = this->getTargetMask();
+        
+        std::queue<MultiTriggerState*>* queue = NULL;
+        // Check for new objects that are in range
+        for(ClassTreeMaskObjectIterator it = targetMask.begin(); it != targetMask.end(); ++it)
+        {
+            WorldEntity* entity = orxonox_cast<WorldEntity*>(*it);
+            if (entity == NULL || this->inRange(entity)) //If the object is no WorldEntity or is already in range.
+                continue;
+
+            Vector3 distanceVec = entity->getWorldPosition() - this->getWorldPosition();
+            if (distanceVec.length() < this->distance_)
+            {
+                if(!this->addToRange(entity))
+                    continue;
+                
+                if(queue == NULL)
+                {
+                    queue = new std::queue<MultiTriggerState*>();
+                }
+                MultiTriggerState* state = new MultiTriggerState;
+                state->bTriggered = true;
+                state->originator = entity;
+                queue->push(state);
+            }
+        }
+        
+        for(std::set<WorldEntity*>::iterator it = this->range_.begin(); it != this->range_.end(); it++)
+        {
+            Vector3 distanceVec = (*it)->getWorldPosition() - this->getWorldPosition();
+            if (distanceVec.length() >= this->distance_)
+            {
+                if(!this->removeFromRange(*it))
+                    continue;
+                
+                if(queue == NULL)
+                {
+                    queue = new std::queue<MultiTriggerState*>();
+                }
+                MultiTriggerState* state = new MultiTriggerState;
+                state->bTriggered = false;
+                state->originator = *it;
+                queue->push(state);
+            }
+        }
+        
+        return queue;
+    }
+    
+}
Index: /code/trunk/src/modules/objects/triggers/DistanceMultiTrigger.h
===================================================================
--- /code/trunk/src/modules/objects/triggers/DistanceMultiTrigger.h	(revision 6800)
+++ /code/trunk/src/modules/objects/triggers/DistanceMultiTrigger.h	(revision 6800)
@@ -0,0 +1,74 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+*/
+
+#ifndef _DistanceMultiTrigger_H__
+#define _DistanceMultiTrigger_H__
+
+#include "objects/ObjectsPrereqs.h"
+
+#include "worldentities/WorldEntity.h"
+#include <set>
+
+#include "MultiTrigger.h"
+
+namespace orxonox
+{
+
+    class _ObjectsExport DistanceMultiTrigger : public MultiTrigger
+    {
+        
+        public:
+            DistanceMultiTrigger(BaseObject* creator);
+            ~DistanceMultiTrigger();
+            
+            void XMLPort(Element& xmlelement, XMLPort::Mode mode);
+            
+            inline void setDistance(float distance)
+                { this->distance_ = distance; }
+            inline float getDistance() const
+                { return this->distance_; }
+                
+        protected:
+            virtual std::queue<MultiTriggerState*>* letTrigger(void);
+            
+            inline bool inRange(WorldEntity* entity)
+                { return this->range_.find(entity) != this->range_.end(); }
+            bool addToRange(WorldEntity* entity)
+                { std::pair<std::set<WorldEntity*>::iterator, bool> pair = this->range_.insert(entity); return pair.second; }
+            bool removeFromRange(WorldEntity* entity)
+                { return this->range_.erase(entity) > 0; }
+                
+        private:
+            float distance_;
+            std::set<WorldEntity*> range_;
+        
+    };
+    
+}
+
+#endif // _DistanceMultiTrigger_H__
Index: /code/trunk/src/modules/objects/triggers/MultiTrigger.cc
===================================================================
--- /code/trunk/src/modules/objects/triggers/MultiTrigger.cc	(revision 6800)
+++ /code/trunk/src/modules/objects/triggers/MultiTrigger.cc	(revision 6800)
@@ -0,0 +1,412 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      Benjamin Knecht
+ *
+*/
+
+#include "MultiTrigger.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+#include "MultiTriggerContainer.h"
+
+namespace orxonox
+{
+    
+    /*static*/ const int MultiTrigger::INF_s = -1;
+    /*static*/ const std::string MultiTrigger::or_s = "or";
+    /*static*/ const std::string MultiTrigger::and_s = "and";
+    /*static*/ const std::string MultiTrigger::xor_s = "xor";
+    
+    CreateFactory(MultiTrigger);
+    
+    //TODO: Clean up.
+    MultiTrigger::MultiTrigger(BaseObject* creator) : StaticEntity(creator)
+    {
+        RegisterObject(MultiTrigger);
+        
+        this->mode_ = MultiTriggerMode::EventTriggerAND;
+
+        this->bFirstTick_ = true;
+
+        this->bInvertMode_ = false;
+        this->bSwitch_ = false;
+        this->bStayActive_ = false;
+        this->delay_ = 0.0f;
+        this->remainingActivations_ = INF_s;
+        this->maxNumSimultaniousTriggerers_ = INF_s;
+        
+        this->targetMask_.exclude(Class(BaseObject));
+
+        this->setSyncMode(0x0);
+        
+    }
+    
+    //TODO: Document
+    MultiTrigger::~MultiTrigger()
+    {
+        COUT(4) << "Destorying MultiTrigger &" << this << ". " << this->stateQueue_.size() << " states still in queue. Deleting." << std::endl;
+        while(this->stateQueue_.size() > 0)
+        {
+            MultiTriggerState* state = this->stateQueue_.front().second;
+            this->stateQueue_.pop_front();
+            delete state;
+        }
+    }
+    
+    //TODO: Clean up?
+    void MultiTrigger::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(MultiTrigger, XMLPort, xmlelement, mode);
+
+        XMLPortParam(MultiTrigger, "delay", setDelay, getDelay, xmlelement, mode).defaultValues(0.0f);
+        XMLPortParam(MultiTrigger, "switch", setSwitch, getSwitch, xmlelement, mode).defaultValues(false);
+        XMLPortParam(MultiTrigger, "stayactive", setStayActive, getStayActive, xmlelement, mode).defaultValues(false);
+        XMLPortParam(MultiTrigger, "activations", setActivations, getActivations, xmlelement, mode).defaultValues(INF_s);
+        XMLPortParam(MultiTrigger, "invert", setInvert, getInvert, xmlelement, mode).defaultValues(false);
+        XMLPortParam(MultiTrigger, "simultaniousTriggerers", setSimultaniousTriggerers, getSimultaniousTriggerers, xmlelement, mode).defaultValues(INF_s);
+        XMLPortParamTemplate(MultiTrigger, "mode", setMode, getModeString, xmlelement, mode, const std::string&).defaultValues(MultiTrigger::and_s);
+        XMLPortParamLoadOnly(MultiTrigger, "target", addTargets, xmlelement, mode).defaultValues("ControllableEntity"); //TODO: Remove load only
+
+        XMLPortObject(MultiTrigger, MultiTrigger, "", addTrigger, getTrigger, xmlelement, mode);
+        
+        COUT(4) << "MultiTrigger &" << this << " created." << std::endl;
+    }
+    
+    //TODO: Document
+    void MultiTrigger::tick(float dt)
+    {
+        if(this->bFirstTick_) // If this is the first tick.
+        {
+            this->bFirstTick_ = false;
+            this->fire(false); //TODO: Does this work? Resp. Is it correct?
+        }
+
+        // Check if the object is active (this is NOT Trigger::isActive()!)
+        if (!this->BaseObject::isActive())
+            return;
+
+        SUPER(MultiTrigger, tick, dt);
+        
+        std::queue<MultiTriggerState*>* queue  = this->letTrigger();
+        if(queue != NULL)
+            COUT(4) << "MultiTrigger &" << this << ": " << queue->size() << " new states to state queue." << std::endl;
+        while(queue != NULL && queue->size() > 0)
+        {
+            //TODO: Be more efficient, Don't delete a state and create a new one immediately after that. Reuse!
+            MultiTriggerState* state = queue->front();
+            this->addState(state->bTriggered & this->isModeTriggered(state->originator), state->originator);
+            queue->pop();
+            delete state;
+        }
+        delete queue;
+
+        if (this->stateQueue_.size() > 0)
+        {
+            MultiTriggerState* state;
+            float timeRemaining;
+            for(int size = this->stateQueue_.size(); size >= 1; size--)
+            {
+                timeRemaining = this->stateQueue_.front().first;
+                state = this->stateQueue_.front().second;
+                if(timeRemaining <= dt)
+                {
+                    if(this->maxNumSimultaniousTriggerers_ == INF_s || this->triggered_.size() < (unsigned int)this->maxNumSimultaniousTriggerers_)
+                    {
+                        // Add the originator to the objects triggering this MultiTrigger.
+                        if(state->bTriggered == true)
+                        {
+                            this->triggered_.insert(state->originator);
+                        }
+                        // Remove the originator from the objects triggering this MultiTrigger.
+                        else
+                        {
+                            this->triggered_.erase(state->originator);
+                        }
+                        
+                        // Add the originator to the objects activating this MultiTrigger.
+                        if(state->bActive == true)
+                        {
+                            this->active_.insert(state->originator);
+                        }
+                        // Remove the originator from the objects activating this MultiTrigger.
+                        else
+                        {
+                            this->active_.erase(state->originator);
+                        }
+                        
+                        // Fire the event.
+                        this->fire(state->bActive, state->originator);
+                    }
+                    
+                    // Remove the state from the state queue.
+                    this->stateQueue_.pop_front();
+                    COUT(4) << "MultiTrigger &" << this << ": State processed, removing from state queue. originator: " << state->originator->getIdentifier()->getName() << " (&" << state->originator << "), active: " << state->bActive << "|" << this->isActive(state->originator) << ", triggered: " << state->bTriggered << "|" << this->isTriggered(state->originator) << "." << std::endl;
+                    delete state;
+                    size -= 1;
+                }
+                else
+                {
+                    this->stateQueue_.push_back(std::pair<float, MultiTriggerState*>(timeRemaining-dt, state));
+                    this->stateQueue_.pop_front();
+                    COUT(4) << "MultiTrigger &" << this << ": State processed, decreasing time remaining. originator: " << state->originator->getIdentifier()->getName() << " (&" << state->originator << "), active: " << state->bActive << ", triggered: " << state->bTriggered << ", time remaining: " << timeRemaining-dt << "." << std::endl;
+                }
+            }
+        }
+    }
+
+    //TODO: Document
+    bool MultiTrigger::isModeTriggered(BaseObject* triggerer)
+    {
+        if (this->children_.size() != 0)
+        {
+            bool returnVal = false;
+
+            switch (this->mode_)
+            {
+                case MultiTriggerMode::EventTriggerAND:
+                    returnVal = checkAnd(triggerer);
+                    break;
+                case MultiTriggerMode::EventTriggerOR:
+                    returnVal = checkOr(triggerer);
+                    break;
+                case MultiTriggerMode::EventTriggerXOR:
+                    returnVal = checkXor(triggerer);
+                    break;
+                default:
+                    returnVal = false;
+                    break;
+            }
+
+            return returnVal;
+        }
+        
+        return true;
+    }
+    
+    //TODO: Document
+    std::queue<MultiTriggerState*>* MultiTrigger::letTrigger(void)
+    {
+        std::queue<MultiTriggerState*>* queue = new std::queue<MultiTriggerState*>();
+        MultiTriggerState* state = new MultiTriggerState;
+        state->bTriggered = true;
+        state->originator = NULL;
+        queue->push(state);
+        return queue;
+    }
+    
+    //TODO: Document
+    bool MultiTrigger::isTriggered(BaseObject* triggerer)
+    {
+        std::set<BaseObject*>::iterator it = this->triggered_.find(triggerer);
+        if(it == this->triggered_.end())
+            return false;
+        return true;
+    }
+
+    //TODO: Document
+    bool MultiTrigger::checkAnd(BaseObject* triggerer)
+    {
+        std::set<MultiTrigger*>::iterator it;
+        for(it = this->children_.begin(); it != this->children_.end(); ++it)
+        {
+            if (!(*it)->isActive(triggerer))
+                return false;
+        }
+        return true;
+    }
+
+    //TODO: Document
+    bool MultiTrigger::checkOr(BaseObject* triggerer)
+    {
+        std::set<MultiTrigger*>::iterator it;
+        for(it = this->children_.begin(); it != this->children_.end(); ++it)
+        {
+            if ((*it)->isActive(triggerer))
+                return true;
+        }
+        return false;
+    }
+
+    //TODO: Document
+    bool MultiTrigger::checkXor(BaseObject* triggerer)
+    {
+        std::set<MultiTrigger*>::iterator it;
+        bool test = false;
+        for(it = this->children_.begin(); it != this->children_.end(); ++it)
+        {
+            if (test && (*it)->isActive(triggerer))
+                return false;
+            if ((*it)->isActive(triggerer))
+                test = true;
+        }
+        return test;
+    }
+    
+    //TODO: Document
+    bool MultiTrigger::addState(bool bTriggered, BaseObject* originator)
+    {
+        if(!this->isTarget(originator))
+            return false;
+        
+        bTriggered ^= this->bInvertMode_;
+        // If the state doesn't change.
+        if(this->isTriggered() && bTriggered)
+            return false;
+        
+        bool bActive = !this->isActive(originator);
+        
+        // If the MultiTrigger is in switch mode.
+        if(this->bSwitch_ && !bTriggered)
+            return false;
+        
+        // If the state changes to active.
+        if(this->remainingActivations_ != INF_s && bActive)
+        {
+            if(this->remainingActivations_ == 0)
+                return false;
+            this->remainingActivations_--;
+        }
+        else
+        {
+            // If the MultiTrigger should stay active and there are no more remaining activations.
+            if(this->bStayActive_ && this->remainingActivations_ == 0)
+                return false;
+        }
+        
+        COUT(4) << "MultiTrigger &" << this << ": State added to state queue. originator: " << originator->getIdentifier()->getName() << " (&" << originator << "), active: " << bActive << "|" << this->isActive(originator) << ", triggered: " << bTriggered << "|" << this->isTriggered(originator) <<  "." << std::endl;
+        
+        // Create state.
+        MultiTriggerState* state = new MultiTriggerState;
+        state->bActive = bActive;
+        state->bTriggered = bTriggered;
+        state->originator = originator;
+        this->stateQueue_.push_back(std::pair<float, MultiTriggerState*>(this->delay_, state));
+        
+        return true;
+    }
+
+    //TODO: Document
+    void MultiTrigger::setMode(const std::string& modeName)
+    {
+        if (modeName == MultiTrigger::and_s)
+            this->setMode(MultiTriggerMode::EventTriggerAND);
+        else if (modeName == MultiTrigger::or_s)
+            this->setMode(MultiTriggerMode::EventTriggerOR);
+        else if (modeName == MultiTrigger::xor_s)
+            this->setMode(MultiTriggerMode::EventTriggerXOR);
+    }
+
+    //TODO: Document
+    const std::string& MultiTrigger::getModeString() const
+    {
+        if (this->mode_ == MultiTriggerMode::EventTriggerAND)
+            return MultiTrigger::and_s;
+        else if (this->mode_ == MultiTriggerMode::EventTriggerOR)
+            return MultiTrigger::or_s;
+        else if (this->mode_ == MultiTriggerMode::EventTriggerXOR)
+            return MultiTrigger::xor_s;
+        else
+            return MultiTrigger::and_s;
+    }
+    
+    //TODO: Document
+    bool MultiTrigger::isActive(BaseObject* triggerer)
+    {
+        std::set<BaseObject*>::iterator it = this->active_.find(triggerer);
+        if(it == this->active_.end())
+            return false;
+        return true;
+    }
+
+    //TODO: Document
+    void MultiTrigger::addTrigger(MultiTrigger* trigger)
+    {
+        if (this != trigger && trigger != NULL)
+            this->children_.insert(trigger);
+    }
+
+    //TODO: Document
+    const MultiTrigger* MultiTrigger::getTrigger(unsigned int index) const
+    {
+        if (this->children_.size() <= index)
+            return NULL;
+
+        std::set<MultiTrigger*>::const_iterator it;
+        it = this->children_.begin();
+
+        for (unsigned int i = 0; i != index; ++i)
+            ++it;
+
+        return (*it);
+    }
+    
+    //TODO: Document
+    void MultiTrigger::fire(bool status, BaseObject* originator)
+    {
+        if(originator == NULL)
+        {
+            this->fireEvent(status);
+            return;
+        }
+        MultiTriggerContainer* container = new MultiTriggerContainer(this, this, originator);
+        this->fireEvent(status, container);
+        COUT(4) << "MultiTrigger &" << this << ": Fired event. originator: " << originator->getIdentifier()->getName() << " (&" << originator << "), status: " << status << "." << std::endl;
+        delete container;
+    }
+    
+    //TODO: Document
+    void MultiTrigger::addTargets(const std::string& targets)
+    {
+        Identifier* target = ClassByString(targets);
+
+        if (target == NULL)
+        {
+            COUT(1) << "Error: \"" << targets << "\" is not a valid class name to include in ClassTreeMask (in " << this->getName() << ", class " << this->getIdentifier()->getName() << ')' << std::endl;
+            return;
+        }
+
+        this->targetMask_.include(target);
+
+        // trigger shouldn't react on itself or other triggers
+        this->targetMask_.exclude(Class(MultiTrigger), true);
+
+        // we only want WorldEntities
+        ClassTreeMask WEMask;
+        WEMask.include(Class(WorldEntity));
+        this->targetMask_ *= WEMask;
+
+        this->notifyMaskUpdate();
+    }
+
+    //TODO: Document
+    void MultiTrigger::removeTargets(const std::string& targets)
+    {
+        Identifier* target = ClassByString(targets);
+        this->targetMask_.exclude(target);
+    }
+    
+}
Index: /code/trunk/src/modules/objects/triggers/MultiTrigger.h
===================================================================
--- /code/trunk/src/modules/objects/triggers/MultiTrigger.h	(revision 6800)
+++ /code/trunk/src/modules/objects/triggers/MultiTrigger.h	(revision 6800)
@@ -0,0 +1,164 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      Benjamin Knecht
+ *
+*/
+
+#ifndef _MultiTrigger_H__
+#define _MultiTrigger_H__
+
+#include "objects/ObjectsPrereqs.h"
+
+#include "core/BaseObject.h"
+#include "core/ClassTreeMask.h"
+
+#include <set>
+#include <deque>
+
+#include "tools/interfaces/Tickable.h"
+#include "worldentities/StaticEntity.h"
+
+namespace orxonox
+{
+    
+    namespace MultiTriggerMode
+    {
+        enum Value
+        {
+            EventTriggerAND,
+            EventTriggerOR,
+            EventTriggerXOR,
+        };
+    }
+    
+    struct MultiTriggerState
+    {
+        BaseObject* originator;
+        bool bActive;
+        bool bTriggered;
+    };
+    
+    class _ObjectsExport MultiTrigger : public StaticEntity, public Tickable
+    {
+        public:
+            MultiTrigger(BaseObject* creator);
+            ~MultiTrigger();
+            
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode);
+            virtual void tick(float dt);
+            
+            bool isActive(BaseObject* triggerer = NULL);
+            void addTrigger(MultiTrigger* trigger);
+            const MultiTrigger* getTrigger(unsigned int index) const;
+            
+            void addTargets(const std::string& targets);
+            void removeTargets(const std::string& targets);
+            inline bool isTarget(BaseObject* target)
+                { return targetMask_.isIncluded(target->getIdentifier()); }
+            
+            void setMode(const std::string& modeName);
+            const std::string& getModeString(void) const;
+            inline void setMode(MultiTriggerMode::Value mode)
+                { this->mode_ = mode; }
+            inline MultiTriggerMode::Value getMode() const
+                { return mode_; }
+
+            inline void setInvert(bool bInvert)
+                { this->bInvertMode_ = bInvert; }
+            inline bool getInvert() const
+                { return this->bInvertMode_; }
+
+            inline void setSwitch(bool bSwitch)
+                { this->bSwitch_ = bSwitch; }
+            inline bool getSwitch() const
+                { return this->bSwitch_; }
+
+            inline void setStayActive(bool bStayActive)
+                { this->bStayActive_ = bStayActive; }
+            inline bool getStayActive() const
+                { return this->bStayActive_; }
+
+            inline void setActivations(int activations)
+                { this->remainingActivations_ = activations; }
+            inline int getActivations() const
+                { return this->remainingActivations_; }
+                
+            inline void setSimultaniousTriggerers(int triggerers)
+                { this->maxNumSimultaniousTriggerers_ = triggerers; }
+            inline int getSimultaniousTriggerers(void)
+                { return this->maxNumSimultaniousTriggerers_; }
+
+            inline void setDelay(float delay)
+                { this->delay_= delay; }
+            inline float getDelay() const
+                { return this->delay_; }
+            
+        protected:
+            void fire(bool status, BaseObject* originator = NULL);
+            
+            bool isModeTriggered(BaseObject* triggerer = NULL);
+            bool isTriggered(BaseObject* triggerer = NULL);
+            
+            virtual std::queue<MultiTriggerState*>* letTrigger(void);
+            
+            inline ClassTreeMask& getTargetMask(void)
+                { return this->targetMask_; }
+            virtual void notifyMaskUpdate(void) {}
+            
+        private:
+            static const int INF_s;
+            static const std::string or_s;
+            static const std::string and_s;
+            static const std::string xor_s;
+            
+            bool addState(bool bTriggered, BaseObject* originator = NULL);
+            
+            bool checkAnd(BaseObject* triggerer);
+            bool checkOr(BaseObject* triggerer);
+            bool checkXor(BaseObject* triggerer);
+
+            bool bFirstTick_;
+
+            MultiTriggerMode::Value mode_;
+            bool bInvertMode_;
+            bool bSwitch_;
+            bool bStayActive_;
+            float delay_;
+            int remainingActivations_;
+            int maxNumSimultaniousTriggerers_;
+            
+            std::set<BaseObject*> active_;
+            std::set<BaseObject*> triggered_;
+
+            std::set<MultiTrigger*> children_;
+            std::deque<std::pair<float, MultiTriggerState*> > stateQueue_;
+            
+            ClassTreeMask targetMask_;
+            
+    };
+
+}
+
+#endif // _MultiTrigger_H__
Index: /code/trunk/src/modules/objects/triggers/MultiTriggerContainer.cc
===================================================================
--- /code/trunk/src/modules/objects/triggers/MultiTriggerContainer.cc	(revision 6800)
+++ /code/trunk/src/modules/objects/triggers/MultiTriggerContainer.cc	(revision 6800)
@@ -0,0 +1,56 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      ...
+ *   Co-authors:
+ *      ...
+ *
+*/
+
+#include "MultiTriggerContainer.h"
+
+#include "core/CoreIncludes.h"
+
+namespace orxonox
+{
+
+    CreateFactory(MultiTriggerContainer);
+    
+    MultiTriggerContainer::MultiTriggerContainer(BaseObject* creator) : BaseObject(creator), originator_(NULL), data_(NULL)
+    {
+        RegisterObject(MultiTriggerContainer);
+        
+    }
+    
+    MultiTriggerContainer::MultiTriggerContainer(BaseObject* creator, MultiTrigger* originator, BaseObject* data) : BaseObject(creator), originator_(originator), data_(data)
+    {
+        RegisterObject(MultiTriggerContainer);
+        
+    }
+    
+    MultiTriggerContainer::~MultiTriggerContainer()
+    {
+        
+    }
+
+
+}
Index: /code/trunk/src/modules/objects/triggers/MultiTriggerContainer.h
===================================================================
--- /code/trunk/src/modules/objects/triggers/MultiTriggerContainer.h	(revision 6800)
+++ /code/trunk/src/modules/objects/triggers/MultiTriggerContainer.h	(revision 6800)
@@ -0,0 +1,59 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      ...
+ *   Co-authors:
+ *      ...
+ *
+*/
+
+#ifndef _MultiTriggerContainer_H__
+#define _MultiTriggerContainer_H__
+
+#include "objects/ObjectsPrereqs.h"
+
+#include "core/BaseObject.h"
+
+namespace orxonox
+{
+
+    class _ObjectsExport MultiTriggerContainer : public BaseObject
+    {
+        public:
+            
+            MultiTriggerContainer(BaseObject* creator);
+            MultiTriggerContainer(BaseObject* creator, MultiTrigger* originator, BaseObject* data);
+            ~MultiTriggerContainer();
+            
+            inline MultiTrigger* getOriginator(void)
+                { return this->originator_; }
+            inline BaseObject* getData(void)
+                { return this->data_; }
+            
+        private:
+            MultiTrigger* originator_;
+            BaseObject* data_;
+    };
+    
+}
+
+#endif // _MultiTriggerContainer_H__
Index: /code/trunk/src/modules/questsystem/CMakeLists.txt
===================================================================
--- /code/trunk/src/modules/questsystem/CMakeLists.txt	(revision 6799)
+++ /code/trunk/src/modules/questsystem/CMakeLists.txt	(revision 6800)
@@ -34,4 +34,5 @@
   LINK_LIBRARIES
     orxonox
+    objects
     overlays
   SOURCE_FILES ${QUESTSYSTEM_SRC_FILES}
Index: /code/trunk/src/modules/questsystem/QuestEffectBeacon.cc
===================================================================
--- /code/trunk/src/modules/questsystem/QuestEffectBeacon.cc	(revision 6799)
+++ /code/trunk/src/modules/questsystem/QuestEffectBeacon.cc	(revision 6800)
@@ -39,4 +39,5 @@
 #include "worldentities/pawns/Pawn.h"
 #include "interfaces/PlayerTrigger.h"
+#include "objects/triggers/MultiTriggerContainer.h"
 #include "QuestEffect.h"
 
@@ -75,5 +76,5 @@
         XMLPortObject(QuestEffectBeacon, QuestEffect, "effects", addEffect, getEffect, xmlelement, mode);
 
-        XMLPortEventState(QuestEffectBeacon, PlayerTrigger, "execute", execute, xmlelement, mode);
+        XMLPortEventState(QuestEffectBeacon, BaseObject, "execute", execute, xmlelement, mode); //TODO: Change BaseObject to MultiTrigger as soon as MultiTrigger is the base of all triggers.
 
         COUT(3) << "New QuestEffectBeacon created." << std::endl;
@@ -84,5 +85,5 @@
         SUPER(QuestEffectBeacon, XMLEventPort, xmlelement, mode);
 
-        XMLPortEventState(QuestEffectBeacon, PlayerTrigger, "execute", execute, xmlelement, mode);
+        XMLPortEventSink(QuestEffectBeacon, BaseObject, "execute", execute, xmlelement, mode);
     }
 
@@ -92,10 +93,13 @@
         This means extracting the Pawn from the PlayerTrigger, provided by the Event causing the execution, and the extracting the PlayerInfo from the received Pawn and invoking the QuestEffectbeacon's QuestEffects on the received PlayerInfo.
     @param trigger
-        Apointer to the PlayerTrigger that threw the Event.
+        A pointer to the PlayerTrigger that threw the Event.
     @return
         Returns true if successfully executed, false if not.
     */
-    bool QuestEffectBeacon::execute(bool b, PlayerTrigger* trigger)
-    {
+    bool QuestEffectBeacon::execute(bool b, BaseObject* trigger)
+    {
+        //TODO: Remove debug output.
+        COUT(1) << "Debug: Calling execute on QuestEffectBeacon." << std::endl;
+        
         if(!b)
         {
@@ -108,11 +112,26 @@
         }
 
-        if(!trigger->isForPlayer()) //!< The PlayerTrigger is not exclusively for Pawns which means we cannot extract one.
-        {
-            return false;
-        }
-
-        //! Extracting the Pawn from the PlayerTrigger.
-        Pawn* pawn = trigger->getTriggeringPlayer();
+        PlayerTrigger* pTrigger = orxonox_cast<PlayerTrigger*>(trigger);
+        MultiTriggerContainer* mTrigger = orxonox_cast<MultiTriggerContainer*>(trigger);
+        Pawn* pawn = NULL;
+        
+        //! If the trigger is neither a Playertrigger nor a MultiTrigger (i.e. a MultitriggerContainer) we can do anything with it.
+        if(pTrigger == NULL && mTrigger == NULL)
+            return false;
+        
+        // If the trigger is a PlayerTrigger.        
+        if(pTrigger != NULL)
+        {
+            if(!pTrigger->isForPlayer())  //!< The PlayerTrigger is not exclusively for Pawns which means we cannot extract one.
+                return false;
+            else
+                pawn = pTrigger->getTriggeringPlayer();
+        }
+        
+        // If the trigger is a MultiTrigger (i.e. a MultiTriggerContainer)
+        if(mTrigger != NULL)
+        {
+            pawn = orxonox_cast<Pawn*>(mTrigger->getData());
+        }
 
         if(pawn == NULL)
Index: /code/trunk/src/modules/questsystem/QuestEffectBeacon.h
===================================================================
--- /code/trunk/src/modules/questsystem/QuestEffectBeacon.h	(revision 6799)
+++ /code/trunk/src/modules/questsystem/QuestEffectBeacon.h	(revision 6800)
@@ -88,5 +88,5 @@
             virtual void XMLEventPort(Element& xmlelement, XMLPort::Mode mode);
 
-            bool execute(bool b, PlayerTrigger* trigger); //!< Executes the QuestEffects of the QuestEffectBeacon.
+            bool execute(bool b, BaseObject* trigger); //!< Executes the QuestEffects of the QuestEffectBeacon.
 
             /**
