Index: code/branches/script_trigger/bin/levels/sample.oxw
===================================================================
--- code/branches/script_trigger/bin/levels/sample.oxw	(revision 1692)
+++ code/branches/script_trigger/bin/levels/sample.oxw	(revision 1693)
@@ -38,5 +38,5 @@
 <Model position="-200,1000,500" scale="10" mesh="hoover_turbine.mesh" yawpitchroll="-90,-90,0" /-->
 
-<Trigger position="0,0,0" scale="2"/>
+<DistanceTrigger position="100,0,0" scale="2" distance="80" delay="10.0" target="SpaceShip"/>
 
 
Index: code/branches/script_trigger/src/orxonox/CMakeLists.txt
===================================================================
--- code/branches/script_trigger/src/orxonox/CMakeLists.txt	(revision 1692)
+++ code/branches/script_trigger/src/orxonox/CMakeLists.txt	(revision 1693)
@@ -26,4 +26,5 @@
   objects/Script.cc
   objects/Trigger.cc
+  objects/DistanceTrigger.cc
 
 #  objects/weapon/AmmunitionDump.cc
Index: code/branches/script_trigger/src/orxonox/objects/DistanceTrigger.cc
===================================================================
--- code/branches/script_trigger/src/orxonox/objects/DistanceTrigger.cc	(revision 1693)
+++ code/branches/script_trigger/src/orxonox/objects/DistanceTrigger.cc	(revision 1693)
@@ -0,0 +1,122 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Benjamin Knecht
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "DistanceTrigger.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+namespace orxonox {
+
+  CreateFactory(DistanceTrigger);
+
+  DistanceTrigger::DistanceTrigger()
+  {
+    RegisterObject(DistanceTrigger);
+
+    targetMask_.exclude(Class(BaseObject));
+  }
+
+  DistanceTrigger::~DistanceTrigger()
+  {
+  }
+
+  void DistanceTrigger::addTarget(Ogre::Node* targetNode)
+  {
+    this->targetSet_.insert(targetNode);
+  }
+
+  void DistanceTrigger::removeTarget(Ogre::Node* targetNode)
+  {
+    int returnval = this->targetSet_.erase(targetNode);
+    if (returnval == 0)
+    {
+      COUT(2) << "Warning: Node " << targetNode << " did not exist in targetSet of trigger " << this << " !" << std::endl;
+      COUT(4) << "Content of targetSet of trigger " << this << " :" << std::endl;
+      std::set<Ogre::Node*>::iterator it;
+      for(it = this->targetSet_.begin(); it != this->targetSet_.end(); it++)
+      {
+        COUT(4) << *it << std::endl;
+      }
+      COUT(4) << "End of targetSet of trigger " << this << std::endl;
+    }
+  }
+
+  void DistanceTrigger::addTargets(std::string targets)
+  {
+    Identifier* targetId = ID(targets);
+    targetMask_.include(targetId);
+    // trigger shouldn't react on itself or other triggers
+    targetMask_.exclude(Class(Trigger), true);
+
+  }
+
+  void DistanceTrigger::removeTargets(std::string targets)
+  {
+    Identifier* targetId = ID(targets);
+    targetMask_.exclude(targetId);
+  }
+
+  bool DistanceTrigger::checkDistance()
+  {
+    // Iterate through all WorldEntities
+    for(Iterator<WorldEntity> it = ObjectList<WorldEntity>::begin(); it; it++)
+    {
+      // check if WorldEntity is a target
+      if(targetMask_.isIncluded(it->getIdentifier()))
+      {
+        Vector3 distanceVec = it->getNode()->getWorldPosition() - this->getNode()->getWorldPosition();
+        if (distanceVec.length() < this->distance_)
+          return true;
+      }
+    }
+    return false;
+
+  }
+
+  void DistanceTrigger::setDistance(float dist)
+  {
+    this->distance_ = dist;
+  }
+
+  void DistanceTrigger::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+  {
+    Trigger::XMLPort(xmlelement, mode);
+
+    XMLPortParamLoadOnly(DistanceTrigger, "distance", setDistance, xmlelement, mode);
+    XMLPortParamLoadOnly(DistanceTrigger, "target", addTargets, xmlelement, mode);
+  }
+
+  bool DistanceTrigger::isTriggered(TriggerMode mode)
+  {
+    if(Trigger::isTriggered(mode))
+      return checkDistance();
+    else
+      return false;
+  }
+}
Index: code/branches/script_trigger/src/orxonox/objects/DistanceTrigger.h
===================================================================
--- code/branches/script_trigger/src/orxonox/objects/DistanceTrigger.h	(revision 1693)
+++ code/branches/script_trigger/src/orxonox/objects/DistanceTrigger.h	(revision 1693)
@@ -0,0 +1,65 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Benjamin Knecht
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _DistanceTrigger_H__
+#define _DistanceTrigger_H__
+
+#include "Trigger.h"
+
+#include <set>
+
+#include <OgreNode.h>
+
+#include "core/ClassTreeMask.h"
+#include "core/BaseObject.h"
+
+namespace orxonox {
+
+  class _OrxonoxExport DistanceTrigger : public Trigger
+  {
+    public:
+      DistanceTrigger();
+      ~DistanceTrigger();
+      void addTarget(Ogre::Node* targetNode);
+      void removeTarget(Ogre::Node* targetNode);
+      void addTargets(std::string targets);
+      void removeTargets(std::string targets);
+      void setDistance(float dist);
+      virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode);
+      bool isTriggered(TriggerMode mode);
+      bool checkDistance();
+
+    private:
+      ClassTreeMask targetMask_;
+      std::set<Ogre::Node*> targetSet_;
+      float distance_;
+  };
+
+}
+
+#endif /* _Trigger_H__ */
Index: code/branches/script_trigger/src/orxonox/objects/Trigger.cc
===================================================================
--- code/branches/script_trigger/src/orxonox/objects/Trigger.cc	(revision 1692)
+++ code/branches/script_trigger/src/orxonox/objects/Trigger.cc	(revision 1693)
@@ -34,4 +34,5 @@
 #include "core/CoreIncludes.h"
 #include "core/ConsoleCommand.h"
+#include "core/XMLPort.h"
 
 namespace orxonox
@@ -46,10 +47,10 @@
     RegisterObject(Trigger);
 
-    targetMask_.exclude(Class(BaseObject));
-
-    //testing
     mode_ = TM_EventTriggerAND;
-    bActive_ = true;
-    triggingTime_ = 100;
+    bActive_ = false;
+    bInvertMode_ = false;
+    delay_ = 0.0;
+    bTriggered_ = false;
+    bUpdating_ = false;
 
     debugBillboard_.setBillboardSet("Examples/Flare", ColourValue(1.0, 0.0, 0.0), 1);
@@ -61,10 +62,11 @@
   }
 
-  bool Trigger::isTriggered()
-  {
-    return this->isTriggered(this->mode_);
-  }
-
-  void Trigger::setVisibility(int bVisible)
+  void Trigger::init()
+  {
+    this->setVisibility(true);
+    timeSinceLastEvent_ = delay_;
+  }
+
+  void Trigger::setVisibility(bool bVisible)
   {
     if(bVisible)
@@ -76,44 +78,114 @@
   void Trigger::tick(float dt)
   {
-    //COUT(0) << "Scale: " << this->getScale() << std::endl;
-    if(bActive_)
-    {
-      //this->actualTime_ += dt;
-      if(this->isTriggered())
+
+    bool newTriggered = this->isTriggered();
+
+
+    // check if new triggering event is really new
+    if(this->latestState_ % 2 != newTriggered)
+    {
+      // create new state
+      if(newTriggered)
       {
-        this->debugBillboard_.getBillboardSet()->getBillboard(0)->setColour(ColourValue(0.0, 1.0, 0.0));
+        latestState_ |= 0x1; // set trigger bit
+        latestState_ ^= 0x10; // toggle state bit
       }
-    }
+      else
+      {
+        latestState_ &= 0x11111110; // set trigger bit
+      }
+
+      // put state change into queue
+      this->stateChanges_.push(std::pair<float,char>(timeSinceLastEvent_, latestState_));
+      // reset time since last event
+      timeSinceLastEvent_ = 0.0;
+
+      if(this->stateChanges_.size() == 1)
+        remainingTime_ = stateChanges_.front().first;
+    }
+
+    if(remainingTime_ > 0.0)
+    {
+      remainingTime_ -= dt;
+      // only increase when acctually waiting for a state in the queue
+      if(timeSinceLastEvent_ >= 0.0)
+        timeSinceLastEvent_ += dt;
+    }
+
+    while(remainingTime_ <= 0.0 && stateChanges_.size() > 0)
+    {
+      // time ran out, change state to new one
+      char newState = stateChanges_.front().second;
+      bTriggered_ = newState % 2;
+      bActive_ = newState>>1 % 2;
+      this->stateChanges_.pop();
+      if(stateChanges_.size() != 0)
+        remainingTime_ = stateChanges_.front().first;
+      else
+        timeSinceLastEvent_ = delay_;
+    }
+
+
+
+    if (bTriggered_ && bActive_)
+      this->setBillboardColour(ColourValue(0.5, 1.0, 0.0));
+    else if (!bTriggered_ && bActive_)
+      this->setBillboardColour(ColourValue(0.0, 1.0, 0.0));
+    else if (bTriggered_ && !bActive_)
+      this->setBillboardColour(ColourValue(1.0, 0.5, 0.0));
+    else
+      this->setBillboardColour(ColourValue(1.0, 0.0, 0.0));
+    bUpdating_ = false;
+  }
+
+  void Trigger::setBillboardColour(ColourValue colour)
+  {
+    this->debugBillboard_.getBillboardSet()->getBillboard(0)->setColour(colour);
   }
 
   bool Trigger::isTriggered(TriggerMode mode)
   {
+    if(bUpdating_)
+      return bTriggered_;
+
     if( children_.size() != 0 )
     {
+      bUpdating_ = true;
+      bool returnval = false;
       switch(mode)
       {
         case TM_EventTriggerAND:
-          return checkAnd();
+          returnval = checkAnd();
           break;
         case TM_EventTriggerOR:
-          return checkOr();
+          returnval = checkOr();
           break;
         case TM_EventTriggerXOR:
-          return checkXor();
-          break;
-        case TM_EventTriggerNOT:
-          return checkNot();
+          returnval = checkXor();
           break;
         default:
-          return false;
+          returnval = false;
           break;
       }
+      if(bInvertMode_)
+        return !returnval;
+      else
+        return returnval;
     }
     return true;
   }
 
+  void Trigger::setDelay(float delay)
+  {
+    this->delay_ = delay;
+  }
+
   void Trigger::XMLPort(Element& xmlelement, XMLPort::Mode mode)
   {
     WorldEntity::XMLPort(xmlelement, mode);
+
+    XMLPortParamLoadOnly(Trigger, "delay", setDelay, xmlelement, mode);
+
+    this->init();
   }
 
@@ -124,17 +196,16 @@
   }
 
-  void Trigger::addTargets(std::string targets)
-  {
-    Identifier* targetId = ID(targets);
-    targetMask_.include(targetId);
-    // trigger shouldn't react on itself or other triggers
-    targetMask_.exclude(Class(Trigger), true);
-  }
-
-  void Trigger::removeTargets(std::string targets)
-  {
-    Identifier* targetId = ID(targets);
-    targetMask_.exclude(targetId);
-  }
+  bool Trigger::switchState()
+  {
+    latestState_ ^= 0x10; // toggle state bit
+    // put state change into queue
+    this->stateChanges_.push(std::pair<float,char>(timeSinceLastEvent_, latestState_));
+    // reset time since last event
+    timeSinceLastEvent_ = 0.0;
+
+    if(this->stateChanges_.size() == 1)
+      remainingTime_ = stateChanges_.front().first;
+  }
+
 
   bool Trigger::checkAnd()
@@ -158,15 +229,4 @@
     }
     return false;
-  }
-
-  bool Trigger::checkNot()
-  {
-    std::set<Trigger*>::iterator it;
-    for(it = this->children_.begin(); it != this->children_.end(); it++)
-    {
-      if((*it)->isTriggered())
-        return false;
-    }
-    return true;
   }
 
@@ -185,24 +245,3 @@
   }
 
-  /*bool Trigger::checkDelay()
-  {
-    if (triggingTime_ < actualTime_)
-      return true;
-    else
-      return false;
-  }
-
-  bool Trigger::checkDistance()
-  {
-    // Iterate through all WorldEntities
-    for(Iterator<WorldEntity> it = ObjectList<WorldEntity>::begin(); it; it++)
-    {
-      Vector3 distanceVec = it->getNode()->getWorldPosition() - this->getNode()->getWorldPosition();
-      if (distanceVec.length() < radius_)
-        return true;
-    }
-    return false;
-
-  }*/
-
 }
Index: code/branches/script_trigger/src/orxonox/objects/Trigger.h
===================================================================
--- code/branches/script_trigger/src/orxonox/objects/Trigger.h	(revision 1692)
+++ code/branches/script_trigger/src/orxonox/objects/Trigger.h	(revision 1693)
@@ -31,10 +31,10 @@
 
 #include <set>
+#include <queue>
 
 #include "OrxonoxPrereqs.h"
 
 #include "WorldEntity.h"
-#include "core/BaseObject.h"
-#include "core/ClassTreeMask.h"
+
 #include "../tools/BillboardSet.h"
 
@@ -46,5 +46,4 @@
     TM_EventTriggerOR,
     TM_EventTriggerXOR,
-    TM_EventTriggerNOT
   };
 
@@ -55,32 +54,35 @@
       ~Trigger();
 
-      bool isTriggered();
-      bool isTriggered(TriggerMode mode);
+      inline bool isTriggered() { return this->isTriggered(this->mode_); }
+      virtual bool isTriggered(TriggerMode mode);
       void addTrigger(Trigger* trig);
-      void addTargets(std::string targets);
-      void removeTargets(std::string targets);
-      void setVisibility(int bVisible);
+      void setVisibility(bool bVisible);
+      void setDelay(float delay);
+      bool switchState();
       virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode);
       inline TriggerMode getMode() { return mode_; }
       inline void setMode(TriggerMode mode) { this->mode_ = mode; }
       void tick(float dt);
-      inline void reset(float time) { this->actualTime_ = 0; this->triggingTime_ = time; }
-      inline void reset() { reset(triggingTime_); }
 
     private:
+      void init();
       bool checkAnd();
       bool checkOr();
       bool checkXor();
-      bool checkNot();
+      void setBillboardColour(ColourValue colour);
 
     private:
       std::set<Trigger*> children_;
+      std::queue<std::pair<float,char> > stateChanges_;
+      float remainingTime_;
+      float timeSinceLastEvent_;
       TriggerMode mode_;
-      float triggingTime_;
-      float actualTime_;
-      float radius_;
       bool bActive_;
-      ClassTreeMask targetMask_;
+      bool bInvertMode_;
+      bool bTriggered_;
+      bool bUpdating_;
       BillboardSet debugBillboard_;
+      float delay_;
+      char latestState_;
   };
 
