[Orxonox-commit 3527] r8213 - in code/trunk: data/levels doc/api/groups src/modules/objects/triggers

dafrick at orxonox.net dafrick at orxonox.net
Sat Apr 9 15:33:06 CEST 2011


Author: dafrick
Date: 2011-04-09 15:33:06 +0200 (Sat, 09 Apr 2011)
New Revision: 8213

Modified:
   code/trunk/data/levels/fightInOurBack.oxw
   code/trunk/data/levels/pirateAttack.oxw
   code/trunk/data/levels/theTimeMachine.oxw
   code/trunk/doc/api/groups/Triggers.dox
   code/trunk/src/modules/objects/triggers/DistanceMultiTrigger.cc
   code/trunk/src/modules/objects/triggers/DistanceMultiTrigger.h
   code/trunk/src/modules/objects/triggers/DistanceTrigger.cc
   code/trunk/src/modules/objects/triggers/DistanceTrigger.h
   code/trunk/src/modules/objects/triggers/EventMultiTrigger.h
   code/trunk/src/modules/objects/triggers/EventTrigger.cc
   code/trunk/src/modules/objects/triggers/EventTrigger.h
   code/trunk/src/modules/objects/triggers/MultiTrigger.cc
   code/trunk/src/modules/objects/triggers/MultiTrigger.h
   code/trunk/src/modules/objects/triggers/Trigger.cc
   code/trunk/src/modules/objects/triggers/Trigger.h
   code/trunk/src/modules/objects/triggers/TriggerBase.h
Log:
Adding changes made to DistanceTrigger also in trunk.
Also documenting trigger.


Modified: code/trunk/data/levels/fightInOurBack.oxw
===================================================================
--- code/trunk/data/levels/fightInOurBack.oxw	2011-04-08 21:51:22 UTC (rev 8212)
+++ code/trunk/data/levels/fightInOurBack.oxw	2011-04-09 13:33:06 UTC (rev 8213)
@@ -134,7 +134,7 @@
                 </execute>
             </events>
             <attached>
-                <DistanceTrigger name="FightInOurBack_MainStart_FollowStart" position="0,0,0" distance="50" target="DistanceTriggerBeacon" targetname="PlayerDistanceTrigger" />
+                <DistanceTrigger name="FightInOurBack_MainStart_FollowStart" position="0,0,0" distance="50" target="Pawn" beaconMode="identify" targetname="PlayerDistanceTrigger" />
                 <!--<Billboard position="0,0,0" colour="1.0,1.0,1.0" material="Examples/Flare" />-->
             </attached>
         </QuestEffectBeacon>
@@ -152,7 +152,7 @@
             </events>
             <attached>
                 <!--<Billboard position="0,0,0" colour="1,1,1" material="Examples/Flare" />-->
-                <DistanceTrigger name="FightInOurBack_FollowEnd_DTranspStart_AssisStart" position="0,0,0" distance="1000" target="DistanceTriggerBeacon" targetname="PlayerDistanceTrigger" stayactive=1 activations=1 />
+                <DistanceTrigger name="FightInOurBack_FollowEnd_DTranspStart_AssisStart" position="0,0,0" distance="1000" target="Pawn" beaconMode="identify" targetname="PlayerDistanceTrigger" stayactive=1 activations=1 />
             </attached>
         </QuestEffectBeacon>
     
@@ -315,7 +315,7 @@
 <!--Creating spaceships (player's team) OK-->
 <!---->
 <!--Trigger to activate this Team (TEAM NO 1)-->
-    <DistanceTrigger name="activateTeam0No1" position="8000,0,3100" distance="1000" target="DistanceTriggerBeacon" targetname="PlayerDistanceTrigger" activations="1" stayactive="true" />
+    <DistanceTrigger name="activateTeam0No1" position="8000,0,3100" distance="1000" target="Pawn" beaconMode="identify" targetname="PlayerDistanceTrigger" activations="1" stayactive="true" />
 
 <!--TEAM NO 1 (activationType : distance || killing a spaceship what belongs to TEAM 0 NO 0)-->
 <?lua for i=0,9,1 do
@@ -475,7 +475,7 @@
 <!--Creating spaceships (enemy) END -->
 
 <Trigger invert=true name="activateFirstSpawnpoint">
-    <DistanceTrigger name="activateSecondSpawnpoint" position="10000,0,3000" distance="1000" target="DistanceTriggerBeacon" targetname="PlayerDistanceTrigger" activations="1" stayactive="true" />
+    <DistanceTrigger name="activateSecondSpawnpoint" position="10000,0,3000" distance="1000" target="Pawn" beaconMode="identify" targetname="PlayerDistanceTrigger" activations="1" stayactive="true" />
 </Trigger>
 
     </Scene>

Modified: code/trunk/data/levels/pirateAttack.oxw
===================================================================
--- code/trunk/data/levels/pirateAttack.oxw	2011-04-08 21:51:22 UTC (rev 8212)
+++ code/trunk/data/levels/pirateAttack.oxw	2011-04-09 13:33:06 UTC (rev 8213)
@@ -141,7 +141,7 @@
                 </execute>
             </events>
             <attached>
-                <DistanceTrigger name=questbeacon1 position="0,0,0" distance=100 target=DistanceTriggerBeacon targetname=Me/>
+                <DistanceTrigger name=questbeacon1 position="0,0,0" distance=100 target="Pawn" beaconMode="identify" targetname=Me/>
             </attached>
             </QuestEffectBeacon>
           </attached>
@@ -155,7 +155,7 @@
         <QuestEffectBeacon position="250,-300,-1500" times=1>
                     <attached>
                         <Billboard position="0,0,0" scale=3 colour="1.0,1.0,0" material="Examples/Flare" />
-                        <DistanceTrigger name=questbeacon2 targetname=Me position="0,0,0" target=DistanceTriggerBeacon distance=400 />
+                        <DistanceTrigger name=questbeacon2 targetname=Me position="0,0,0" target="Pawn" beaconMode="identify" distance=400 />
                     </attached>
                     <effects>
                         <AddQuest questId="3159b4d4-bc86-4190-ba1d-4530668dfe31" />
@@ -170,7 +170,7 @@
         <!-- Hint to first Quest-->
         <QuestEffectBeacon position="0,0,0" times=1>
                     <attached>
-                        <DistanceTrigger name=questbeacon3  position="0,0,0" distance=300 target=DistanceTriggerBeacon targetname=Me delay="5" />
+                        <DistanceTrigger name=questbeacon3  position="0,0,0" distance=300 target="Pawn" beaconMode="identify" targetname=Me delay="5" />
                     </attached>
                     <effects>
                         <AddQuestHint hintId="2b85f32c-2433-4f1a-bdd4-f24d20c9403c" />
@@ -187,7 +187,7 @@
         <QuestEffectBeacon position="600,300,-6000" times=1>
                     <attached>
                         <Billboard position="0,0,0" scale=3 colour="0,1.0,0" material="Examples/Flare" />
-                        <DistanceTrigger name=questbeacon4  position="0,0,0" distance=200 target=DistanceTriggerBeacon targetname=Me />
+                        <DistanceTrigger name=questbeacon4  position="0,0,0" distance=200 target="Pawn" beaconMode="identify" targetname=Me />
                     </attached>
     
                     <effects>
@@ -206,7 +206,7 @@
         <!-- Wrong way 1-->
         <QuestEffectBeacon position="7600,300,-8000" times=1>
                     <attached>
-                        <DistanceTrigger name=questbeacon5  position="0,0,0" distance=300 target=DistanceTriggerBeacon targetname=Me />
+                        <DistanceTrigger name=questbeacon5  position="0,0,0" distance=300 target="Pawn" beaconMode="identify" targetname=Me />
                     </attached>
                     <effects>
                         <AddQuest questId="9930a598-98bc-4ff8-8cc0-31311a6ccaaa" />
@@ -221,7 +221,7 @@
         <!-- Wrong way 2-->
         <QuestEffectBeacon position="1600,2300,-10000" times=1>
                     <attached>
-                        <DistanceTrigger name=questbeacon8  position="0,0,0" distance=300 target=DistanceTriggerBeacon targetname=Me />
+                        <DistanceTrigger name=questbeacon8  position="0,0,0" distance=300 target="Pawn" beaconMode="identify" targetname=Me />
                     </attached>
                     <effects>
                         <AddQuest questId="9930a598-98bc-4ff8-8cc0-31311a6ccaab" />
@@ -236,7 +236,7 @@
         <!-- Base found!-->
         <QuestEffectBeacon position="4600,5300,-11000" times=1>
                     <attached>
-                        <DistanceTrigger name=questbeacon6  position="0,0,0" distance=600 target=DistanceTriggerBeacon targetname=Me />
+                        <DistanceTrigger name=questbeacon6  position="0,0,0" distance=600 target="Pawn" beaconMode="identify" targetname=Me />
                     </attached>
                     <effects>
                         <CompleteQuest questId="8d8ed3a6-74a6-4491-9172-26155cff151d" />
@@ -254,7 +254,7 @@
         <!--Stick found-->
         <QuestEffectBeacon position="4800,5785,-10725" times=1>
                     <attached>
-                        <DistanceTrigger name=questbeacon7  position="0,0,0" distance=30 target=DistanceTriggerBeacon targetname=Me />
+                        <DistanceTrigger name=questbeacon7  position="0,0,0" distance=30 target="Pawn" beaconMode="identify" targetname=Me />
                     </attached>
                     <effects>
                         <CompleteQuest questId="8a62408b-c47b-4e02-bd3d-06bb9ec0b363" />
@@ -273,7 +273,7 @@
         <QuestEffectBeacon position="4000,4000,-20000" times=1>
                     <attached>
                         <Billboard position="0,0,0" scale=3 colour="0,0,1.0" material="Examples/Flare" />
-                        <DistanceTrigger name=questbeacon9 position="0,0,0" distance=500 target=DistanceTriggerBeacon targetname=Me />
+                        <DistanceTrigger name=questbeacon9 position="0,0,0" distance=500 target="Pawn" beaconMode="identify" targetname=Me />
                     </attached>
                     <effects>
                         <CompleteQuest questId="85380d05-b791-45d1-82e9-01f0bc930367" />

Modified: code/trunk/data/levels/theTimeMachine.oxw
===================================================================
--- code/trunk/data/levels/theTimeMachine.oxw	2011-04-08 21:51:22 UTC (rev 8212)
+++ code/trunk/data/levels/theTimeMachine.oxw	2011-04-09 13:33:06 UTC (rev 8213)
@@ -93,7 +93,7 @@
 <!--Triggers (used for the Time Machine effect)___________________________________________________________________________________________________________________________________________-->
     
         <!--TRIGGERS IF THE PLAYERS REACHES THE "TIME MACHINE"-->
-        <DistanceTrigger name="EnterTimeMachine" position="0,0,0" distance="100" target="DistanceTriggerBeacon" targetname="PlayerDistanceTrigger" >
+        <DistanceTrigger name="EnterTimeMachine" position="0,0,0" distance="100" target="Pawn" beaconMode="identify" targetname="PlayerDistanceTrigger" >
             <attached>
                 <Billboard position="0,0,0" material="Examples/Flare" colour="0, 0, 1" scale=1/>
                 <Billboard position="100,0,0" material="Examples/Flare" colour="0, 0, 1" scale=1/>

Modified: code/trunk/doc/api/groups/Triggers.dox
===================================================================
--- code/trunk/doc/api/groups/Triggers.dox	2011-04-08 21:51:22 UTC (rev 8212)
+++ code/trunk/doc/api/groups/Triggers.dox	2011-04-09 13:33:06 UTC (rev 8213)
@@ -6,24 +6,87 @@
 
     @defgroup NormalTrigger Trigger
     @ingroup Triggers
+    
+    @ref orxonox::Trigger "Triggers" are objects which react to certain events by changing their boolean state. That state is the trigger's activity @ref orxonox::Trigger can be either <em>active</em> or <em>not active</em>.
+    
+    @section TriggerTechnicalDetails Technical Details
+    A common @ref orxonox::Trigger "Trigger" is an object that can either be <em>active</em> or <em>inactive</em>, with a specified behavior how to switch between the two. Each time a switch occurs an @ref orxonox::Event "Event" is fired (see the @ref Eventsystem "Eventsystem" for more information about how that works exactly), with th @ref orxonox::Trigger "Trigger" as the originator. This way the entity that reacts to the @ref orxonox::Trigger "Trigger" triggering receives information about the @ref orxonox::Trigger "Trigger" that created the @ref orxonox::Event "Event". If the @ref orxonox::Trigger "Trigger" is also a @ref orxonox::PlayerTrigger "PlayerTrigger", under some conditions, the entity that caused the @ref orxonox::Trigger "Trigger" to trigger can be accessed.
 
+    Also, just as with all triggers, @ref orxonox::Trigger "Triggers" can be nested (even with e.g. @ref orxonox::MultiTrigger "MultiTriggers").
+    @code
+    <Trigger switch="true" delay="2">
+        <DistanceTrigger position="100,0,0" distance="80" />
+        <EventMultiTrigger ... />
+    </Trigger>
+    @endcode
+
+    @ref orxonox::Trigger "Triggers" also allow for additional complexity which can be added through the choice of the parameters explained below.
+    But first it is important to understand a small implementation detail. There is a distinction between the @ref orxonox::Trigger "Trigger" being triggered (there is the state <em>triggered</em> for that) and the @ref orxonox::Trigger "Trigger" being active (for that is the state <em>activity</em>). From the outside only the <em>activity</em> is visible. The state <em>triggered</em> tells us whether the trigger is actually triggered, but it could pretend (for some reason, some of which we will see shortly) to be <em>active</em> to the outside, while it in fact isn't. The standard behavior is, that the <em>activity</em> changes, when the @ref orxonox::Trigger "Trigger" transits from being <em>triggered</em> to being <em>not triggered</em> or the other way around.
+
+    The parameters of the @ref orxonox::Trigger "Trigger" are: 
+    - @b delay The delay is the time in seconds, that the trigger waits until it reacts (i.e. changes it's state) to the triggering condition being fulfilled. Internally this is handled by a state queue coupled with a counter, for each state that is delayed. The state becomes <em>active</em> when the counter runs out. This allows the @ref orxonox::Trigger "Trigger" to work even if the delay changes at runtime. However if the delay changes it only affects newly arriving states not the ones already in the queue. The default is <code>0.0</code>.
+    - @b switch Switch is a boolean, if <code>true</code> the @ref orxonox::Trigger "Trigger" is in <em>switch-mode</em>, meaning, that the <em>activity</em> changes only when the trigger is <em>triggered</em>, not when it is <em>not triggered</em> (Just like a light switch does). This means, that in <em>switch-mode</em> the <em>activity</em> only changes, when the trigger changes from being <em>not triggered</em> to being <em>triggered</em> but not the other way around. The default is <code>false</code>.
+    - @b stayActive Stay active is also a boolean, if <code>true</code> the @ref orxonox::Trigger "Trigger" stays active after it has been activated as many times as specified by the parameter <em>activations</em>. In essence this means, that after the last time it is activated it cannot be deactivated. The default is <code>false</code>.
+    - @b activations Activations is the number of times the @ref orxonox::Trigger "Trigger" can be activated until the trigger can't be triggered anymore. The default is <code>-1</code>, which denotes infinity.
+    - @b invert Invert is a boolean, if <code>true</code> the @ref orxonox::Trigger "Trigger" is in <em>invert-mode</em>, meaning, that if the triggering condition is fulfilled the @ref orxonox::Trigger "Trigger" will have the state <em>not triggered</em> and and if the condition is not fulfilled it will have the state <em>triggered</em>. In short it inverts the behavior of the @ref orxonox::Trigger "Trigger". The default is <code>false</code>.
+    - @b mode The mode describes how the @ref orxonox::Trigger "Trigger" acts in relation to all the triggers (its children), that are appended to it. There are 3 modes: <em>and</em>, meaning that the @ref orxonox::Trigger "Trigger" can only be triggered if all the appended triggers are active. <em>or</em>, meaning that the @ref orxonox::Trigger "Trigger" can only be triggered if at least one of the appended triggers is active. And <em>xor</em>, meaning that the @ref orxonox::Trigger "Trigger" can only be triggered if one and only one appended trigger is active. Note, that I wrote 'can only be active', that implies, that there is an additional condition to the <em>activity</em> of the @ref orxonox::Trigger "Trigger" and that is the fulfillment of the triggering condition (the @ref orxonox::Trigger "Trigger" class itself doesn't have one, but all derived classes should). Also bear in mind, that the <em>activity</em> of a @ref orxonox::Trigger "Trigger" is still coupled to the object that triggered it. The default is <em>and</em>.
+
+    @subsection Sub-typesOfTriggers Sub-types of Triggers
+
+    @subsubsection EventTrigger EventTrigger
+    An @ref orxonox::EventTrigger "EventTrigger" can either be used to be triggered when an @ref orxonox::Event "Event", that itself is triggering, arrives at its event port.
+
+    A common usage could look like this:
+    @code
+    <EventTrigger invert="true" delay="1">
+        <events>
+            <trigger>
+                <Trigger ... />
+                <Trigger ... />
+            </trigger>
+        </events>
+    </EventTrigger>
+    @endcode
+
+    @subsubsection DistanceTrigger DistanceTrigger
+    The @ref orxonox::DistanceTrigger "DistanceTrigger" is a Trigger that triggers whenever an object (that is of the specified target type) is in a specified range of the @ref orxonox::DistanceTrigger "DistanceTrigger". The object can be specified further by setting the <em>beaconMode</em> and attaching a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon" to the object.
+    Parameters are (additional to the ones of Trigger):
+    - @b distance Which specifies the maximum distance at which the @ref orxonox::DistanceTrigger "DistanceTrigger" still triggers, i.e. its range. Default is <code>100</code>.
+    - @b target Which specifies the class of objects that can trigger the @ref orxonox::DistanceTrigger "DistanceTrigger". Default is <code>"Pawn"</code>.
+    - @b beaconMode Which specifies, whether the @ref orxonox::DistanceTrigger "DistanceTrigger" operates on @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacons" or not. If <em>off</em> the DistanceMultiTrigger works as usual. If set to <em>identify</em> the @ref orxonox::DistanceTrigger "DistanceTrigger" is only triggered by objects that have a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon", with the same name as specified in <em>targetname</em>, attached to them. If set to <em>exclude</em> the @ref orxonox::DistanceTrigger "DistanceTrigger" is only triggered by objects that don't have a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon", with the same name as specified in <em>targetname</em>, attached to them. Default is <em>off</em>.
+    - @b targetname Which specifies the name @ref oroxnox::DistanceTriggerBeacon "DistanceTriggerBeacons" need to have to make the @ref orxonox::DistanceTrigger "DistanceTrigger" react to them if it is in <em>beacon-mode</em> (the beaconMode is not <em>off</em>).
+
+    A simple @ref orxonox::DistanceTrigger "DistanceTrigger" could look like this:
+    @code
+    <DistanceTrigger position="0,0,0" switch="true" target="Pawn" distance="20" />
+    @endcode
+
+    An implementation that only reacts to objects with a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon" attached would look like this:
+    @code
+    <DistanceTrigger position="0,0,0" target="Pawn" beaconMode="identify" targetname="beacon1" distance="30" />
+    @endcode
+    This particular @ref orxonox::DistanceTrigger "DistanceTrigger" would only react if an object was in range, that had a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon" with the name <em>beacon1</em> attached.
+
     @defgroup MultiTrigger MultiTrigger
     @ingroup Triggers
 
-    @ref orxonox::MultiTrigger "MultiTriggers" are (as they are @ref orxonox::TriggerBase "Triggers") objects which react to certain events. They offer all the functionality that the common @ref orxonox::Trigger "Triggers" do with one significant difference. The common @ref orxonox::Trigger "Trigger" has just one state, it can either be <em>triggered</em> or <em>not triggered</em>, it doesn't discriminate between who's triggering (or not triggering) it. A @ref orxonox::MultiTrigger "MultiTrigger", on the other hand, has a distinct state (<em>triggered</em> or <em>not triggered</em>) for each entity that is defined as being able to trigger said @ref orxonox::MultiTrigger "MultiTrigger".
+    @ref orxonox::MultiTrigger "MultiTriggers" are (as they are @ref orxonox::TriggerBase "Triggers") objects which react to certain events. They offer all the functionality that the common @ref orxonox::Trigger "Triggers" do with one significant difference. The common @ref orxonox::Trigger "Trigger" has just one state, it can either be <em>active</em> or <em>not acive</em>, it doesn't discriminate between who's triggering (or not triggering) it. A @ref orxonox::MultiTrigger "MultiTrigger", on the other hand, has a distinct state (<em>active</em> or <em>not actve</em>) for each entity that is defined as being able to trigger said @ref orxonox::MultiTrigger "MultiTrigger".
 
-    This difference becomes significant, when, for example, you want a @ref orxonox::DistanceTrigger "DistanceTrigger" to trigger a @ref orxonox::QuestEffectBeacon "QuestEffectBeacon" to hand out a @ref orxonox::Quest "Quest" to any @ref orxonox::Pawn "Pawn" that enters its range. With a simple @ref orxonox::DistanceTrigger "DistanceTrigger" (as opposed to the more complex @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger") the first @ref orxonox::Pawn "Pawn" to be in range would trigger it an receive the @ref orxonox::Quest "Quest", however if a second @ref orxonox::Pawn "Pawn" would enter the range, while the first @ref orxonox::Pawn "Pawn" still is in the range nothing would happen and even after the first @ref orxonox::Pawn "Pawn" left nothing would happen, since the whole time the @ref orxonox::DistanceTrigger "DistanceTrigger" would just be triggered. In contrast with a @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" the first @ref orxonox::Pawn "Pawn" would enter the range and the @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" would have the state <em>triggered</em> for this exact @ref orxonox::Pawn "Pawn" (but for none else) and thus the @ref orxonox::Pawn "Pawn" would receive the @ref orxonox::Quest "Quest" and when the second @ref orxonox::Pawn "Pawn" enters the range the state of the @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" for that second @ref orxonox::Pawn "Pawn" would change to <em>triggered</em> and it would receive the @ref orxonox::Quest "Quest" as well.
+    This difference becomes significant, when, for example, you want a @ref orxonox::DistanceTrigger "DistanceTrigger" to trigger a @ref orxonox::QuestEffectBeacon "QuestEffectBeacon" to hand out a @ref orxonox::Quest "Quest" to any @ref orxonox::Pawn "Pawn" that enters its range. With a simple @ref orxonox::DistanceTrigger "DistanceTrigger" (as opposed to the more complex @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger") the first @ref orxonox::Pawn "Pawn" to be in range would trigger it an receive the @ref orxonox::Quest "Quest", however if a second @ref orxonox::Pawn "Pawn" would enter the range, while the first @ref orxonox::Pawn "Pawn" still is in the range nothing would happen and even after the first @ref orxonox::Pawn "Pawn" left nothing would happen, since the whole time the @ref orxonox::DistanceTrigger "DistanceTrigger" would just be <em>active</em>. In contrast with a @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" the first @ref orxonox::Pawn "Pawn" would enter the range and the @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" would have the state <em>active</em> for this exact @ref orxonox::Pawn "Pawn" (but for none else) and thus the @ref orxonox::Pawn "Pawn" would receive the @ref orxonox::Quest "Quest" and when the second @ref orxonox::Pawn "Pawn" enters the range the state of the @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" for that second @ref orxonox::Pawn "Pawn" would change to <em>active</em> and it would receive the @ref orxonox::Quest "Quest" as well.
 
     @section WhenToUseMultiTriggers When to use MultiTriggers
     Consequentially you would use @ref orxonox::MultiTrigger "MultiTriggers" (instead of common @ref orxonox::Trigger "Triggers"), when it is important that the trigger has different states for each triggering entity and when that fact is essential in the concept of the object that reacts to the triggering. However you should not just use @ref orxonox::MultiTrigger "MultiTrigger" instead of @ref orxonox::Trigger "Trigger", when in doubt, because @ref orxonox::MultiTrigger "MultiTrigger" produces significantly more overhead than @ref orxonox::Trigger "Trigger" due to the added complexity.
 
     @section HowToUseMultiTriggers How to use MultiTriggers
     ...
+    
+    @section HowToCreateANewMultiTrigger How to create a new MultiTrigger.
+    ...
 
     @section MultiTriggerTechnicalDetails Technical Details
-    A common @ref orxonox::Trigger "Trigger" is an object that can either be <em>active</em> or <em>inactive</em>, with a specified behavior how to switch between the two. A @ref orxonox::MultiTrigger "MultiTrigger" generalizes that behavior for multiple objects triggering the trigger. A @ref orxonox::MultiTrigger "MultiTrigger" can be <em>active</em> or <em>inactive</em> for any object triggering it, with the state for each object being completely independent of the state for all other objects. Each time a switch occurs an @ref orxonox::Event "Event" is fired, with a @ref orxonox::MultiTriggerContainer "MultiTriggerContainer" as the originator, containing a pointer to the @ref orxonox::MultiTrigger "MultiTrigger" that caused the @ref orxonox::Event "Event" and a pointer to the object that caused the trigger to change it's activity. This way the entity that reacts to the @ref orxonox::MultiTrigger "MultiTrigger" triggering receives the information it needs about the entity that triggered the @ref orxonox::MultiTrigger "MultiTrigger".
+    A common @ref orxonox::Trigger "Trigger" is an object that can either be <em>active</em> or <em>inactive</em>, with a specified behavior how to switch between the two. A @ref orxonox::MultiTrigger "MultiTrigger" generalizes that behavior for multiple objects triggering the trigger. A @ref orxonox::MultiTrigger "MultiTrigger" can be <em>active</em> or <em>inactive</em> for any object triggering it, with the state for each object being completely independent of the state for all other objects. Each time a switch occurs an @ref orxonox::Event "Event" is fired (see the @ref Eventsystem "Eventsystem" for more information about how that works exactly), with a @ref orxonox::MultiTriggerContainer "MultiTriggerContainer" as the originator, containing a pointer to the @ref orxonox::MultiTrigger "MultiTrigger" that caused the @ref orxonox::Event "Event" and a pointer to the object that caused the trigger to change it's activity. This way the entity that reacts to the @ref orxonox::MultiTrigger "MultiTrigger" triggering receives the information it needs about the entity that triggered the @ref orxonox::MultiTrigger "MultiTrigger".
 
-    Also, just as with all triggers, @ref orxonox::MultiTrigger "MultiTriggers" can be nested (event with triggers other than @ref orxonox::MultiTrigger "MultiTriggers").
+    Also, just as with all triggers, @ref orxonox::MultiTrigger "MultiTriggers" can be nested (even with triggers other than @ref orxonox::MultiTrigger "MultiTriggers").
     @code
     <MultiTrigger switch="true" delay="2">
         <DistanceMultiTrigger position="100,0,0" distance="80" />
@@ -32,10 +95,10 @@
     @endcode
 
     @ref orxonox::MultiTrigger "MultiTriggers" also allow for additional complexity which can be added through the choice of the parameters (some of which are also present in the common @ref orxonox::Trigger "Trigger") explained (briefly) below.
-    But first it is important to understand a small implementational detail. There is a distinction between the @ref orxonox::MultiTrigger "MultiTrigger" being triggered (there is the state <em>triggered</em> for that) and the @ref orxonox::MultiTrigger "MultiTrigger" being active (for that is the state <em>activity</em>). From the outside only the <em>activity</em> is visible (and has above been referred to as <em>triggered</em> for the sake of comprehensibility). The state <em>triggered</em> tells us whether the trigger is actually triggered, but it could pretend (for some reason, some of which we will see shortly) to be <em>triggered</em> to the outside, while it in fact isn't (but it would then be <em>active</em>). The standard behavior is, that the <em>activity</em> changes, when the @ref orxonox::MultiTrigger "MultiTrigger" transits from being triggered to not being triggered or the other way around. So to the inside a @ref orxonox::MultiTrigger "MultiTrigger" being <em>active</em> is synonymous to the @ref orxonox::MultiTrigger "MultiTrigger" being <em>triggered</em> to the outside.
+    But first it is important to understand a small implementation detail. There is a distinction between the @ref orxonox::MultiTrigger "MultiTrigger" being triggered (there is the state <em>triggered</em> for that) and the @ref orxonox::MultiTrigger "MultiTrigger" being active (for that is the state <em>activity</em>). From the outside only the <em>activity</em> is visible. The state <em>triggered</em> tells us whether the trigger is actually triggered, but it could pretend (for some reason, some of which we will see shortly) to be <em>active</em> to the outside, while it in fact isn't. The standard behavior is, that the <em>activity</em> changes, when the @ref orxonox::MultiTrigger "MultiTrigger" transits from being <em>triggered</em> to being <em>not triggered</em> or the other way around.
 
     The parameters of the @ref orxonox::MultiTrigger "MultiTrigger" are: 
-    - @b delay The delay is the time in seconds, that the trigger waits until it reacts (i.e. changes it's state) to the triggering condition being fulfilled. Internally this is handled by a state queue coupled with a counter, for each state that is delayed. The state becomes <em>active</em> when the counter runs out. This allows the @ref orxonox::MultiTrigger "MultiTrigger" to work even if the delay changes at runtime. However if the delay changes it only affects newly arriving states not the ones already in the queue. The default is <code>0</code>.
+    - @b delay The delay is the time in seconds, that the trigger waits until it reacts (i.e. changes it's state) to the triggering condition being fulfilled. Internally this is handled by a state queue coupled with a counter, for each state that is delayed. The state becomes <em>active</em> when the counter runs out. This allows the @ref orxonox::MultiTrigger "MultiTrigger" to work even if the delay changes at runtime. However if the delay changes it only affects newly arriving states not the ones already in the queue. The default is <code>0.0</code>.
     - @b switch Switch is a boolean, if <code>true</code> the @ref orxonox::MultiTrigger "MultiTrigger" is in <em>switch-mode</em>, meaning, that the <em>activity</em> changes only when the trigger is triggered, not when it is un-triggered (Just like a light switch does). This means, that in <em>switch-mode</em> the <em>activity</em> only changes, when the trigger changes from not being triggered to being triggered but not the other way around. The default is <code>false</code>.
     - @b stayActive Stay active is also a boolean, if <code>true</code> the @ref orxonox::MultiTrigger "MultiTrigger" stays active after it has been activated as many times as specified by the parameter <em>activations</em>. In essence this means, that after the last time it is activated it cannot be deactivated. The default is <code>false</code>.
     - @b activations Activations is the number of times the @ref orxonox::MultiTrigger "MultiTrigger" can be activated until the trigger can't be triggered anymore. The default is <code>-1</code>, which denotes infinity.
@@ -63,17 +126,22 @@
     @endcode
 
     @subsubsection DistanceMultiTrigger DistanceMultiTrigger
-    A @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" is the MultiTrigger equivalent of the @ref orxonox::DistanceTrigger "DistanceTrigger" and works just the same way. It triggers (now separately for each object triggering it, since it's a @ref orxonox::MultiTrigger "MultiTrigger") whenever an object that is a target of the @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" is in the specified range.
+    A @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" is the @ref orxonox::MultiTrigger "MultiTrigger" equivalent of the @ref orxonox::DistanceTrigger "DistanceTrigger" and works just the same way. It triggers (now separately for each object triggering it, since it's a @ref orxonox::MultiTrigger "MultiTrigger") whenever an object that is a target of the @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" is in the specified range.
 
-    Two additional parameters can be specified for the @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" are the <em>distance</em>, which defines the maximum distance at which an object still triggers the @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger", and the <em>targetname</em>. Setting the <em>targename</em> puts the @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" in <em>single-target mode</em>. In this mode the @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger"  can only be triggered by objects that have a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon" with the name specified by <em>targetname</em> directly attached. For the <em>single-target mode</em> to work the target of the @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" has to be set to <code>DistanceTriggerBeacon</code>.
+    The target object can be specified further by setting the <em>beaconMode</em> and attaching a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon" to the object.
+    Parameters are (additional to the ones of @ref orxonox::MultiTrigger "MultiTrigger"):
+    - @b distance Which specifies the maximum distance at which the @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" still triggers. Default is <code>100</code>.
+    - @b beaconMode Which specifies, whether the @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" operates on @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacons" or not. If <em>off</em> the @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" works as usual. If set to <em>identify</em> the @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" is only triggered by objects that have a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon", with the same name as specified in <em>targetname</em>, attached to them. If set to <em>exclude</em> the @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" is only triggered by objects that don't have a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon", with the same name as specified in <em>targetname</em>, attached to them. Default is <em>off</em>.
+    - @b targetname Which specifies the name @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacons" need to have to make the @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" react to them if it is in <em>beacon-mode</em> (the beaconMode is not <em>off</em>).
 
-    A common usage (without @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon") would look like this:
+    A simple @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" could look like this:
     @code
-    <DistanceMultiTrigger position="0,0,0" switch="true" target="Pawn" distance="20" />
+    <@ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" position="0,0,0" switch="true" target="Pawn" distance="20" />
     @endcode
 
-    With @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon" it would look like this:
+    An implementation that only reacts to objects with a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon" attached would look like this:
     @code
-    <DistanceMultiTrigger position="0,0,0" target="DistanceMultiTrigger" targetname="beacon1" distance="30" />
+    <@ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" position="0,0,0" target="Pawn" beaconMode="identify" targetname="beacon1" distance="30" />
     @endcode
+    This particular @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" would only react if an object was in range, that had a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon" with the name <em>beacon1</em> attached.
 */

Modified: code/trunk/src/modules/objects/triggers/DistanceMultiTrigger.cc
===================================================================
--- code/trunk/src/modules/objects/triggers/DistanceMultiTrigger.cc	2011-04-08 21:51:22 UTC (rev 8212)
+++ code/trunk/src/modules/objects/triggers/DistanceMultiTrigger.cc	2011-04-09 13:33:06 UTC (rev 8213)
@@ -42,19 +42,23 @@
 namespace orxonox
 {
 
+    /*static*/ const std::string DistanceMultiTrigger::beaconModeOff_s = "off";
+    /*static*/ const std::string DistanceMultiTrigger::beaconModeIdentify_s = "identify";
+    /*static*/ const std::string DistanceMultiTrigger::beaconModeExlcude_s = "exclude";
+    
     CreateFactory(DistanceMultiTrigger);
 
     /**
     @brief
         Default Constructor. Registers the object and initializes default values.
     */
-    DistanceMultiTrigger::DistanceMultiTrigger(BaseObject* creator) : MultiTrigger(creator)
+    DistanceMultiTrigger::DistanceMultiTrigger(BaseObject* creator) : MultiTrigger(creator), beaconMask_(NULL)
     {
         RegisterObject(DistanceMultiTrigger);
 
         this->distance_ = 100.0f;
+        this->setBeaconModeDirect(distanceMultiTriggerBeaconMode::off);
         this->targetName_ = "";
-        this->singleTargetMode_ = false;
     }
 
     /**
@@ -63,7 +67,8 @@
     */
     DistanceMultiTrigger::~DistanceMultiTrigger()
     {
-
+        if(this->beaconMask_ != NULL)
+            delete this->beaconMask_;
     }
 
     /**
@@ -75,6 +80,7 @@
         SUPER(DistanceMultiTrigger, XMLPort, xmlelement, mode);
 
         XMLPortParam(DistanceMultiTrigger, "distance", setDistance, getDistance, xmlelement, mode);
+        XMLPortParam(DistanceMultiTrigger, "beaconMode", setBeaconMode, getBeaconMode, xmlelement, mode);
         XMLPortParam(DistanceMultiTrigger, "targetname", setTargetName, getTargetName, xmlelement, mode);
     }
 
@@ -125,21 +131,41 @@
         }
 
         // Check for new objects that are in range
-        for(ClassTreeMaskObjectIterator it = this->getTargetMask().begin(); it != this->getTargetMask().end(); ++it)
+        ClassTreeMask targetMask = this->getTargetMask();
+        // If we are in identify-mode another target mask has to be applies to find the DistanceTriggerBeacons.
+        if(this->beaconMode_ == distanceMultiTriggerBeaconMode::identify)
+            targetMask = *this->beaconMask_;
+
+        // Iterate through all objects that are targets of the DistanceMultiTrigger.
+        for(ClassTreeMaskObjectIterator it = targetMask.begin(); it != targetMask.end(); ++it)
         {
             WorldEntity* entity = static_cast<WorldEntity*>(*it);
 
-            // If the DistanceMultiTrigger is in single-target mode.
-            if(this->singleTargetMode_)
+            // If the DistanceMultiTrigger is in identify-mode and the DistanceTriggerBeacon attached to the object has the wrong name we ignore it.
+            if(this->beaconMode_ == distanceMultiTriggerBeaconMode::identify)
             {
-                // If the object that is a target is no DistanceTriggerBeacon, then the DistanceMultiTrigger can't be in single-target mode.
-                if(!entity->isA(ClassIdentifier<DistanceTriggerBeacon>::getIdentifier()))
+                if(entity->getName() != this->targetName_)
+                    continue;
+                // If the object, the DistanceTriggerBeacon is attached to, is not a target of this DistanceMultiTrigger.
+                else if(this->getTargetMask().isExcluded(entity->getParent()->getIdentifier()))
+                    continue;
+            }
+            
+            // If the DistanceMultiTrigger is in exclude mode and the DistanceTriggerBeacon attached to the object has the right name, we ignore it.
+            if(this->beaconMode_ == distanceMultiTriggerBeaconMode::exclude)
+            {
+                
+                const std::set<WorldEntity*> attached = entity->getAttachedObjects();
+                bool found = false;
+                for(std::set<WorldEntity*>::const_iterator it = attached.begin(); it != attached.end(); it++)
                 {
-                    this->singleTargetMode_ = false;
-                    COUT(2) << "DistanceMultiTrigger " << this->getName() << " (&" << this <<  ")" << "is in single-target mode but the target is '" << entity->getIdentifier()->getName() << "' instead of DistanceTriggerBeacon. Setting single-target mode to false." << std::endl;
+                    if((*it)->isA(ClassIdentifier<DistanceTriggerBeacon>::getIdentifier()) && static_cast<DistanceTriggerBeacon*>(*it)->getName() == this->targetName_)
+                    {
+                        found = true;
+                        break;
+                    }
                 }
-                // If the target name and the name of the DistancTriggerBeacon don't match.
-                else if(entity->getName().compare(this->targetName_) != 0)
+                if(found)
                     continue;
             }
 
@@ -152,8 +178,8 @@
                 if(!this->addToRange(entity))
                     continue;
 
-                // Change the entity to the parent of the DistanceTriggerBeacon (if in single-target-mode), which is the entity to which the beacon is attached.
-                if(this->singleTargetMode_)
+                // Change the entity to the parent of the DistanceTriggerBeacon (if in identify-mode), which is the entity to which the beacon is attached.
+                if(this->beaconMode_ == distanceMultiTriggerBeaconMode::identify)
                     entity = entity->getParent();
 
                 // If no queue has been created, yet.
@@ -170,22 +196,62 @@
 
         return queue;
     }
-
+    
     /**
     @brief
-        Set the target name of DistanceTriggerBeacons that triggers this DistanceMultiTrigger.
-    @param targetname
-        The name of the DistanceTriggerBeacon as a string.
+        Set the beacon mode.
+    @param mode
+        The mode as an enum.
     */
-    void DistanceMultiTrigger::setTargetName(const std::string& targetname)
+    void DistanceMultiTrigger::setBeaconModeDirect(distanceMultiTriggerBeaconMode::Value mode)
     {
-        // If the targetname is no blank string single-target mode is enabled.
-        if(targetname != "")
-            this->singleTargetMode_ = true;
+        this->beaconMode_ = mode;
+        if(this->beaconMode_ == distanceMultiTriggerBeaconMode::identify && this->beaconMask_ == NULL)
+        {
+            this->beaconMask_ = new ClassTreeMask();
+            this->beaconMask_->exclude(Class(BaseObject));
+            this->beaconMask_->include(Class(DistanceTriggerBeacon));
+        }
+    }
+    
+    /**
+    @brief
+        Get the beacon mode.
+    @return
+        Returns the mode as a string.
+    */
+    const std::string& DistanceMultiTrigger::getBeaconMode(void) const
+    {
+        switch(this->getBeaconModeDirect())
+        {
+            case distanceMultiTriggerBeaconMode::off :
+                return DistanceMultiTrigger::beaconModeOff_s;
+            case distanceMultiTriggerBeaconMode::identify:
+                return DistanceMultiTrigger::beaconModeIdentify_s;
+            case distanceMultiTriggerBeaconMode::exclude:
+                return DistanceMultiTrigger::beaconModeExlcude_s;
+            default :
+                assert(0); // This is impossible.
+                return BLANKSTRING;
+        }
+    }
+    
+    /**
+    @brief
+        Set the beacon mode.
+    @param mode
+        The mode as a string.
+    */
+    void DistanceMultiTrigger::setBeaconMode(const std::string& mode)
+    {
+        if(mode == DistanceMultiTrigger::beaconModeOff_s)
+            this->setBeaconModeDirect(distanceMultiTriggerBeaconMode::off);
+        else if(mode == DistanceMultiTrigger::beaconModeIdentify_s)
+            this->setBeaconModeDirect(distanceMultiTriggerBeaconMode::identify);
+        else if(mode == DistanceMultiTrigger::beaconModeExlcude_s)
+            this->setBeaconModeDirect(distanceMultiTriggerBeaconMode::exclude);
         else
-            this->singleTargetMode_ = false;
-
-        this->targetName_ = targetname;
+            COUT(1) << "Invalid beacon mode in DistanceMultiTrigger." << endl;
     }
 
     /**

Modified: code/trunk/src/modules/objects/triggers/DistanceMultiTrigger.h
===================================================================
--- code/trunk/src/modules/objects/triggers/DistanceMultiTrigger.h	2011-04-08 21:51:22 UTC (rev 8212)
+++ code/trunk/src/modules/objects/triggers/DistanceMultiTrigger.h	2011-04-09 13:33:06 UTC (rev 8213)
@@ -50,24 +50,40 @@
 
     /**
     @brief
-        The DistanceMultiTrigger is a MultiTrigger that triggers whenever an object (that is of the specified target type) is in a specified range of the DistanceMultiTrigger. The object can be specified further by adding a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon" (by just attaching it) to the objects that can trigger this DistanceMultiTrigger and specify the name of the @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon" with the parameter <em>targetname</em> and only objects that have a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon" with that name will trigger the DistanceMultiTrigger.
+        Enum for the beacon mode of the DistanceMultiTrigger.
+        
+    @ingroup MultiTrigger
+    */
+    namespace distanceMultiTriggerBeaconMode
+    {
+        enum Value {
+            off, //!< The DistanceMultiTrigger is not in <em>beacon-mode</em>.
+            identify, //!< The DistanceTrigger is in <em>identify-mode</em>.
+            exclude //!< The DistanceTrigger is in <em>exclude-mode</em>.
+        };
+    }
+
+    /**
+    @brief
+        The DistanceMultiTrigger is a MultiTrigger that triggers whenever an object (that is of the specified target type) is in a specified range of the DistanceMultiTrigger. The object can be specified further by setting the <em>beaconMode</em> and attaching a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon" to the object.
         Parameters are (additional to the ones of MultiTrigger):
-        - @b distance Which specifies the maximum distance at which the DistanceMultiTrigger still triggers. Default is 100.
-        - @b targetname Which, if not left blank, causes the DistancMultiTrigger to be in <em>single-target</em> mode, meaning, that it only reacts to objects that have a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon" (therefore the target has to be set to @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon" for it to work), with the name specified by <em>targetname</em>, attached.
+        - @b distance Which specifies the maximum distance at which the DistanceMultiTrigger still triggers. Default is <code>100</code>.
+        - @b beaconMode Which specifies, whether the DistanceMultiTrigger operates on @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacons" or not. If <em>off</em> the DistanceMultiTrigger works as usual. If set to <em>identify</em> the DistanceMultiTrigger is only triggered by objects that have a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon", with the same name as specified in <em>targetname</em>, attached to them. If set to <em>exclude</em> the DistanceMultiTrigger is only triggered by objects that don't have a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon", with the same name as specified in <em>targetname</em>, attached to them. Default is <em>off</em>.
+        - @b targetname Which specifies the name @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacons" need to have to make the DistanceMultiTrigger react to them if it is in <em>beacon-mode</em> (the beaconMode is not <em>off</em>).
 
-        A simple DistanceMultiTrigger would look like this:
+        A simple DistanceMultiTrigger could look like this:
         @code
         <DistanceMultiTrigger position="0,0,0" switch="true" target="Pawn" distance="20" />
         @endcode
 
         An implementation that only reacts to objects with a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon" attached would look like this:
         @code
-        <DistanceMultiTrigger position="0,0,0" target="DistanceMultiTrigger" targetname="beacon1" distance="30" />
+        <DistanceMultiTrigger position="0,0,0" target="Pawn" beaconMode="identify" targetname="beacon1" distance="30" />
         @endcode
         This particular DistanceMultiTrigger would only react if an object was in range, that had a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon" with the name <em>beacon1</em> attached.
 
     @see MultiTrigger
-        For more information on MultiTriggers.
+        For more information on @ref orxonox::MultiTrigger "MultiTriggers".
 
     @author
         Damian 'Mozork' Frick
@@ -78,20 +94,12 @@
     {
 
         public:
-            DistanceMultiTrigger(BaseObject* creator); //!< Default Constructor. Registers the object and initializes default values.
-            virtual ~DistanceMultiTrigger(); //!< Destructor.
+            DistanceMultiTrigger(BaseObject* creator); // Default Constructor. Registers the object and initializes default values.
+            virtual ~DistanceMultiTrigger(); // Destructor.
 
-            void XMLPort(Element& xmlelement, XMLPort::Mode mode); //!< Method for creating a DistanceMultiTrigger object through XML.
-
-            void setTargetName(const std::string& targetname); //!< Set the target name of DistanceTriggerBeacons that triggers this DistanceMultiTrigger.
+            void XMLPort(Element& xmlelement, XMLPort::Mode mode); // Method for creating a DistanceMultiTrigger object through XML.
+            
             /**
-            @brief Get the target name of the DistanceTriggerbeacon, that triggers this DistanceMultiTrigger.
-            @return Returns the target name as a string.
-            */
-            inline const std::string& getTargetName(void)
-                { return this->targetName_; }
-
-            /**
             @brief Set the distance at which the DistanceMultiTrigger triggers.
             @param distance The distance.
             */
@@ -103,17 +111,47 @@
             */
             inline float getDistance() const
                 { return this->distance_; }
+            
+            void setBeaconModeDirect(distanceMultiTriggerBeaconMode::Value mode); // Set the beacon mode.
+            /**
+            @brief Get the beacon mode.
+            @return Returns the mode as an enum.
+            */
+            inline distanceMultiTriggerBeaconMode::Value getBeaconModeDirect(void) const
+                { return this->beaconMode_; }
+            void setBeaconMode(const std::string& mode); // Set the beacon mode.
+            const std::string& getBeaconMode(void) const; // Get the beacon mode.
 
+            /**
+            @brief Set the target name of DistanceTriggerBeacons that triggers this DistanceMultiTrigger.
+            @param targetname The name of the DistanceTriggerBeacon as a string.
+            */
+            inline void setTargetName(const std::string& targetname)
+                { this->targetName_ = targetname; }
+            /**
+            @brief Get the target name of the DistanceTriggerbeacon, that triggers this DistanceMultiTrigger.
+            @return Returns the target name as a string.
+            */
+            inline const std::string& getTargetName(void) const
+                { return this->targetName_; }
+
         protected:
-            virtual std::queue<MultiTriggerState*>* letTrigger(void); //!< This method is called by the MultiTrigger to get information about new trigger events that need to be looked at.
+            virtual std::queue<MultiTriggerState*>* letTrigger(void); // This method is called by the MultiTrigger to get information about new trigger events that need to be looked at.
 
-            bool addToRange(WorldEntity* entity); //!< Add a given entity to the entities, that currently are in range of the DistanceMultiTrigger.
-            bool removeFromRange(WorldEntity* entity); //!< Remove a given entity from the set of entities, that currently are in range of the DistanceMultiTrigger.
+            bool addToRange(WorldEntity* entity); // Add a given entity to the entities, that currently are in range of the DistanceMultiTrigger.
+            bool removeFromRange(WorldEntity* entity); // Remove a given entity from the set of entities, that currently are in range of the DistanceMultiTrigger.
 
         private:
+            //! Strings for the beacon modes.
+            static const std::string beaconModeOff_s;
+            static const std::string beaconModeIdentify_s;
+            static const std::string beaconModeExlcude_s;
+            
             float distance_; //!< The distance at which the DistanceMultiTrigger triggers.
+
+            distanceMultiTriggerBeaconMode::Value beaconMode_; //!< The beacon mode, the DistanceMultiTrigger is in.
             std::string targetName_; //!< The target name, used in <em>single-target</em> mode.
-            bool singleTargetMode_; //!< To indicate whe the MultiDistanceTrigger is in <em>single-target</em> mode.
+            ClassTreeMask* beaconMask_; //!< A mask, that only accepts DistanceTriggerBeacons.
 
             std::map<WorldEntity*, WeakPtr<WorldEntity>* > range_; //!< The set of entities that currently are in range of the DistanceMultiTrigger.
 

Modified: code/trunk/src/modules/objects/triggers/DistanceTrigger.cc
===================================================================
--- code/trunk/src/modules/objects/triggers/DistanceTrigger.cc	2011-04-08 21:51:22 UTC (rev 8212)
+++ code/trunk/src/modules/objects/triggers/DistanceTrigger.cc	2011-04-09 13:33:06 UTC (rev 8213)
@@ -36,147 +36,257 @@
 
 #include "core/CoreIncludes.h"
 #include "core/XMLPort.h"
+
 #include "worldentities/pawns/Pawn.h"
+
 #include "DistanceTriggerBeacon.h"
 
 namespace orxonox
 {
-  CreateFactory(DistanceTrigger);
 
-  DistanceTrigger::DistanceTrigger(BaseObject* creator) : Trigger(creator)
-  {
-    RegisterObject(DistanceTrigger);
+    /*static*/ const std::string DistanceTrigger::beaconModeOff_s = "off";
+    /*static*/ const std::string DistanceTrigger::beaconModeIdentify_s = "identify";
+    /*static*/ const std::string DistanceTrigger::beaconModeExlcude_s = "exclude";
 
-    this->distance_ = 100;
-    this->targetMask_.exclude(Class(BaseObject));
-    this->targetName_ = "";
-    this->singleTargetMode_ = false;
-  }
+    CreateFactory(DistanceTrigger);
 
-  DistanceTrigger::~DistanceTrigger()
-  {
-  }
+    /**
+    @brief
+        Constructor. Registers and initializes the object.
+    @param creator
+        The creator of this trigger.
+    */
+    DistanceTrigger::DistanceTrigger(BaseObject* creator) : Trigger(creator), beaconMask_(NULL)
+    {
+        RegisterObject(DistanceTrigger);
 
-  void DistanceTrigger::XMLPort(Element& xmlelement, XMLPort::Mode mode)
-  {
-    SUPER(DistanceTrigger, XMLPort, xmlelement, mode);
+        this->distance_ = 100;
+        this->targetMask_.exclude(Class(BaseObject));
+        this->targetName_ = "";
+    }
 
-    XMLPortParam(DistanceTrigger, "distance", setDistance, getDistance, xmlelement, mode).defaultValues(100.0f);
-    XMLPortParamLoadOnly(DistanceTrigger, "target", addTargets, xmlelement, mode).defaultValues("Pawn");
-    XMLPortParam(DistanceTrigger, "targetname", setTargetName, getTargetName, xmlelement, mode);
-  }
-
-  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)
+    /**
+    @brief
+        Destructor.
+    */
+    DistanceTrigger::~DistanceTrigger()
     {
-      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;
+        // Delete the beacon mask if it exists.
+        if(this->beaconMask_ != NULL)
+            delete this->beaconMask_;
     }
-  }
 
-  void DistanceTrigger::addTargets(const std::string& targets)
-  {
-    Identifier* targetId = ClassByString(targets);
+    /**
+    @brief
+        Method for creating a DistanceTrigger object through XML.
+    */
+    void DistanceTrigger::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(DistanceTrigger, XMLPort, xmlelement, mode);
 
-    //! Checks whether the target is (or is derived from) a ControllableEntity.
-    Identifier* pawnId = Class(Pawn);
-    Identifier* distanceTriggerBeaconId = Class(DistanceTriggerBeacon);
-    if(targetId->isA(pawnId) || targetId->isA(distanceTriggerBeaconId))
-    {
-      this->setForPlayer(true);
+        XMLPortParam(DistanceTrigger, "distance", setDistance, getDistance, xmlelement, mode).defaultValues(100.0f);
+        XMLPortParamLoadOnly(DistanceTrigger, "target", addTarget, xmlelement, mode).defaultValues("Pawn");
+        XMLPortParam(DistanceTrigger, "beaconMode", setBeaconMode, getBeaconMode, xmlelement, mode);
+        XMLPortParam(DistanceTrigger, "targetname", setTargetName, getTargetName, xmlelement, mode);
     }
 
-    if (!targetId)
+    /**
+    @brief
+        Add some target to the DistanceTrigger.
+    @param targetStr
+        The target class name as a string.
+    */
+    void DistanceTrigger::addTarget(const std::string& targetStr)
     {
-        COUT(1) << "Error: \"" << targets << "\" is not a valid class name to include in ClassTreeMask (in " << this->getName() << ", class " << this->getIdentifier()->getName() << ')' << std::endl;
-        return;
-    }
+        Identifier* targetId = ClassByString(targetStr);
 
-    this->targetMask_.include(targetId);
+        // Checks whether the target is (or is derived from) a Pawn and if so set the PlayerTrigger aspect of this trigger to be for the player, meaning, that from this Trigger one can derive the Pawn that caused it to trigger.
+        Identifier* pawnId = Class(Pawn);
+        if(targetId->isA(pawnId))
+            this->setForPlayer(true);
 
-    // trigger shouldn't react on itself or other triggers
-    this->targetMask_.exclude(Class(Trigger), true);
+        if (targetId == NULL)
+        {
+            COUT(1) << "Error: \"" << targetStr << "\" is not a valid class name to include in ClassTreeMask (in " << this->getName() << ", class " << this->getIdentifier()->getName() << ')' << std::endl;
+            return;
+        }
 
-    // we only want WorldEntities
-    ClassTreeMask WEMask;
-    WEMask.include(Class(WorldEntity));
-    this->targetMask_ *= WEMask;
+        // Add the target to the target mask.
+        this->targetMask_.include(targetId);
 
-    this->notifyMaskUpdate();
-  }
+        // The DistanceTrigger shouldn't react to itself or other triggers.
+        this->targetMask_.exclude(Class(TriggerBase), true);
 
-  void DistanceTrigger::removeTargets(const std::string& targets)
-  {
-    Identifier* targetId = ClassByString(targets);
-    this->targetMask_.exclude(targetId);
-  }
+        // We only want WorldEntities (since only they have a position)
+        ClassTreeMask WEMask;
+        WEMask.include(Class(WorldEntity));
+        this->targetMask_ *= WEMask;
 
-  bool DistanceTrigger::checkDistance()
-  {
-    // Iterate through all objects
-    for (ClassTreeMaskObjectIterator it = this->targetMask_.begin(); it != this->targetMask_.end(); ++it)
+        this->notifyMaskUpdate(); // Inform interested parties that the target mask has been updated.
+    }
+
+    /**
+    @brief
+        Remove some target from the DistanceTrigger.
+    @param targetStr
+        The target class name as a string.
+    */
+    void DistanceTrigger::removeTarget(const std::string& targetStr)
     {
-      WorldEntity* entity = orxonox_cast<WorldEntity*>(*it);
-      if (!entity)
-        continue;
+        Identifier* targetId = ClassByString(targetStr);
+        this->targetMask_.exclude(targetId);
+    }
 
-      // If the DistanceTrigger is in single-target mode.
-      if(this->singleTargetMode_)
-      {
-        // If the object that is a target is no DistanceTriggerBeacon, then the DistanceTrigger can't be in single-target-mode.
-        if(!(*it)->isA(ClassIdentifier<DistanceTriggerBeacon>::getIdentifier()))
+    /**
+    @brief
+        Check, whether there are entities that are targets of this DistanceTrigger in its range.
+    @return
+        Returns true if there are valid entities in its range.
+    */
+    bool DistanceTrigger::checkDistance()
+    {
+        // Check whether there is a cached object, it still exists and whether it is still in range, if so nothing further needs to be done.
+        if(this->cache_.get() != NULL)
         {
-          this->singleTargetMode_ = false;
-          COUT(2) << "DistanceTrigger " << this->getName() << " (&" << this <<  ")" << "is in single-target mode but the target is '" << entity->getIdentifier()->getName() << "' instead of DistanceTriggerBeacon. Setting single-target mode to false." << std::endl;
+            if((this->cache_.get()->getWorldPosition() - this->getWorldPosition()).length() < this->distance_)
+                return true;
+            else
+                this->cache_.reset();
         }
-        // If the target name and the name of the DistancTriggerBeacon don't match.
-        else if(entity->getName().compare(this->targetName_) != 0)
-          continue;
-      }
+        
+        // Check for new objects that are in range
+        ClassTreeMask targetMask = this->targetMask_;
+        // If we are in identify-mode another target mask has to be applies to find the DistanceTriggerBeacons.
+        if(this->beaconMode_ == distanceTriggerBeaconMode::identify)
+            targetMask = *this->beaconMask_;
 
-      Vector3 distanceVec = entity->getWorldPosition() - this->getWorldPosition();
-      if (distanceVec.length() < this->distance_)
-      {
-
-        // If the target is a player (resp. is a, or is derived from a, ControllableEntity) the triggeringPlayer is set to the target entity.
-        if(this->isForPlayer())
+        // Iterate through all objects that are targets of the DistanceTrigger.
+        for (ClassTreeMaskObjectIterator it = targetMask.begin(); it != targetMask.end(); ++it)
         {
+            WorldEntity* entity = static_cast<WorldEntity*>(*it);
 
-          // Change the entity to the parent of the DistanceTriggerBeacon (if in single-target-mode), which is the entity to which the beacon is attached.
-          if(this->singleTargetMode_)
-            entity = entity->getParent();
+            // If the DistanceTrigger is in identify-mode and the DistanceTriggerBeacon attached to the object has the wrong name we ignore it.
+            if(this->beaconMode_ == distanceTriggerBeaconMode::identify)
+            {
+                if(entity->getName() != this->targetName_)
+                    continue;
+                // If the object, the DistanceTriggerBeacon is attached to, is not a target of this DistanceMultiTrigger.
+                else if(this->targetMask_.isExcluded(entity->getParent()->getIdentifier()))
+                    continue;
+            }
 
-          Pawn* player = orxonox_cast<Pawn*>(entity);
-          this->setTriggeringPlayer(player);
+            // If the DistanceTrigger is in exclude mode and the DistanceTriggerBeacon attached to the object has the right name, we ignore it.
+            if(this->beaconMode_ == distanceTriggerBeaconMode::exclude)
+            {
+
+                const std::set<WorldEntity*> attached = entity->getAttachedObjects();
+                bool found = false;
+                for(std::set<WorldEntity*>::const_iterator it = attached.begin(); it != attached.end(); it++)
+                {
+                    if((*it)->isA(ClassIdentifier<DistanceTriggerBeacon>::getIdentifier()) && static_cast<DistanceTriggerBeacon*>(*it)->getName() == this->targetName_)
+                    {
+                        found = true;
+                        break;
+                    }
+                }
+                if(found)
+                    continue;
+            }
+
+            // Check if the entity is in range.
+            Vector3 distanceVec = entity->getWorldPosition() - this->getWorldPosition();
+            if (distanceVec.length() < this->distance_)
+            {
+                // If the target is a player (resp. is a, or is derived from a, Pawn) the triggeringPlayer is set to the target entity.
+                if(this->isForPlayer())
+                {
+                    // Change the entity to the parent of the DistanceTriggerBeacon (if in identify-mode), which is the entity to which the beacon is attached.
+                    if(this->beaconMode_ == distanceTriggerBeaconMode::identify)
+                        entity = entity->getParent();
+
+                    Pawn* player = orxonox_cast<Pawn*>(entity);
+                    this->setTriggeringPlayer(player);
+                }
+                
+                // Add the entity to the cache.
+                this->cache_ = WeakPtr<WorldEntity>(entity);
+
+                return true;
+            }
         }
 
-        return true;
-      }
+        return false;
     }
 
-    return false;
-  }
+    /**
+    @brief
+        Set the beacon mode.
+    @param mode
+        The mode as an enum.
+    */
+    void DistanceTrigger::setBeaconModeDirect(distanceTriggerBeaconMode::Value mode)
+    {
+        this->beaconMode_ = mode;
+        if(this->beaconMode_ == distanceTriggerBeaconMode::identify && this->beaconMask_ == NULL)
+        {
+            this->beaconMask_ = new ClassTreeMask();
+            this->beaconMask_->exclude(Class(BaseObject));
+            this->beaconMask_->include(Class(DistanceTriggerBeacon));
+        }
+    }
 
-  bool DistanceTrigger::isTriggered(TriggerMode::Value mode)
-  {
-    if (Trigger::isTriggered(mode))
+    /**
+    @brief
+        Get the beacon mode.
+    @return
+        Returns the mode as a string.
+    */
+    const std::string& DistanceTrigger::getBeaconMode(void) const
     {
-      return checkDistance();
+        switch(this->getBeaconModeDirect())
+        {
+            case distanceTriggerBeaconMode::off :
+                return DistanceTrigger::beaconModeOff_s;
+            case distanceTriggerBeaconMode::identify:
+                return DistanceTrigger::beaconModeIdentify_s;
+            case distanceTriggerBeaconMode::exclude:
+                return DistanceTrigger::beaconModeExlcude_s;
+            default :
+                assert(0); // This is impossible.
+                return BLANKSTRING;
+        }
     }
-    else
-      return false;
-  }
+
+    /**
+    @brief
+        Set the beacon mode.
+    @param mode
+        The mode as a string.
+    */
+    void DistanceTrigger::setBeaconMode(const std::string& mode)
+    {
+        if(mode == DistanceTrigger::beaconModeOff_s)
+            this->setBeaconModeDirect(distanceTriggerBeaconMode::off);
+        else if(mode == DistanceTrigger::beaconModeIdentify_s)
+            this->setBeaconModeDirect(distanceTriggerBeaconMode::identify);
+        else if(mode == DistanceTrigger::beaconModeExlcude_s)
+            this->setBeaconModeDirect(distanceTriggerBeaconMode::exclude);
+        else
+            COUT(1) << "Invalid beacon mode in DistanceTrigger." << endl;
+    }
+
+    /**
+    @brief
+        Check whether the DistanceTrigger is triggered.
+        It is triggered if it is triggered according only to its mode (i.e. its sub-triggers) and if a target is in range.
+    @param
+        Returns true if it is triggered ,false if not.
+    */
+    bool DistanceTrigger::isTriggered(TriggerMode::Value mode)
+    {
+        if (Trigger::isTriggered(mode))
+            return checkDistance();
+        else
+            return false;
+    }
 }

Modified: code/trunk/src/modules/objects/triggers/DistanceTrigger.h
===================================================================
--- code/trunk/src/modules/objects/triggers/DistanceTrigger.h	2011-04-08 21:51:22 UTC (rev 8212)
+++ code/trunk/src/modules/objects/triggers/DistanceTrigger.h	2011-04-09 13:33:06 UTC (rev 8213)
@@ -38,61 +38,133 @@
 #include "objects/ObjectsPrereqs.h"
 
 #include <set>
+
 #include "core/ClassTreeMask.h"
-#include "Trigger.h"
+
 #include "interfaces/PlayerTrigger.h"
 
+#include "Trigger.h"
+
 namespace orxonox
 {
-
+    
   /**
   @brief
-
-  @author
-    Benjamin Knecht
-  @author
-    Damian 'Mozork' Frick
-
+      Enum for the beacon mode of the DistanceTrigger.
+      
   @ingroup NormalTrigger
   */
-  class _ObjectsExport DistanceTrigger : public Trigger, public PlayerTrigger
+  namespace distanceTriggerBeaconMode
   {
-    public:
-      DistanceTrigger(BaseObject* creator);
-      virtual ~DistanceTrigger();
+      enum Value {
+          off,
+          identify,
+          exclude
+      };
+  }
 
-      virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode);
+    /**
+    @brief
+        The DistanceTrigger is a Trigger that triggers whenever an object (that is of the specified target type) is in a specified range of the DistanceTrigger. The object can be specified further by setting the <em>beaconMode</em> and attaching a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon" to the object.
+        Parameters are (additional to the ones of Trigger):
+        - @b distance Which specifies the maximum distance at which the DistanceTrigger still triggers, i.e. its range. Default is <code>100</code>.
+        - @b target Which specifies the class of objects that can trigger the DistanceTrigger. Default is <code>"Pawn"</code>.
+        - @b beaconMode Which specifies, whether the DistanceTrigger operates on @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacons" or not. If <em>off</em> the DistanceMultiTrigger works as usual. If set to <em>identify</em> the DistanceTrigger is only triggered by objects that have a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon", with the same name as specified in <em>targetname</em>, attached to them. If set to <em>exclude</em> the DistanceTrigger is only triggered by objects that don't have a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon", with the same name as specified in <em>targetname</em>, attached to them. Default is <em>off</em>.
+        - @b targetname Which specifies the name @ref oroxnox::DistanceTriggerBeacon "DistanceTriggerBeacons" need to have to make the DistanceTrigger react to them if it is in <em>beacon-mode</em> (the beaconMode is not <em>off</em>).
 
-      void addTarget(Ogre::Node* targetNode);
-      void addTargets(const std::string& targets);
-      void removeTarget(Ogre::Node* targetNode);
-      void removeTargets(const std::string& targets);
+        A simple DistanceTrigger could look like this:
+        @code
+        <DistanceTrigger position="0,0,0" switch="true" target="Pawn" distance="20" />
+        @endcode
 
-      inline void setTargetName(const std::string& targetname)
-        { if(targetname != "") this->singleTargetMode_ = true; else this->singleTargetMode_ = false; this->targetName_ = targetname; }
-      inline const std::string& getTargetName(void)
-        { return this->targetName_; }
+        An implementation that only reacts to objects with a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon" attached would look like this:
+        @code
+        <DistanceTrigger position="0,0,0" target="Pawn" beaconMode="identify" targetname="beacon1" distance="30" />
+        @endcode
+        This particular DistanceTrigger would only react if an object was in range, that had a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon" with the name <em>beacon1</em> attached.
 
-      inline void setDistance(float distance)
-        { this->distance_ = distance; }
-      inline float getDistance() const
-        { return this->distance_; }
+    @see Trigger
+        For more information on @ref orxonox::Trigger "Triggers".
 
-      bool checkDistance();
+    @author
+        Benjamin Knecht
+    @author
+        Damian 'Mozork' Frick
 
-    protected:
-      virtual bool isTriggered(TriggerMode::Value mode);
-      virtual void notifyMaskUpdate() {}
+    @ingroup NormalTrigger
+    */
+    class _ObjectsExport DistanceTrigger : public Trigger, public PlayerTrigger
+    {
+        public:
+            DistanceTrigger(BaseObject* creator); // Constructor. Registers and initializes the object.
+            virtual ~DistanceTrigger();
 
-      ClassTreeMask targetMask_;
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode); // Method for creating a DistanceTrigger object through XML.
 
-    private:
-      std::set<Ogre::Node*> targetSet_;
-      std::string targetName_;
-      float distance_;
-      bool singleTargetMode_;
+            void addTarget(const std::string& targets); // Add some target to the DistanceTrigger.
+            void removeTarget(const std::string& targets); // Remove some target from the DistanceTrigger.
 
-  };
+            /**
+            @brief Set the range of the DistanceTrigger.
+            @param distance The range to be set.
+            */
+            inline void setDistance(float distance)
+                { this->distance_ = distance; }
+            /**
+            @brief Get the range of the DistanceTrigger.
+            @return Returns the range of the distance trigger.
+            */
+            inline float getDistance() const
+                { return this->distance_; }
+
+            void setBeaconModeDirect(distanceTriggerBeaconMode::Value mode); // Set the beacon mode.
+            /**
+            @brief Get the beacon mode.
+            @return Returns the mode as an enum.
+            */
+            inline distanceTriggerBeaconMode::Value getBeaconModeDirect(void) const
+            { return this->beaconMode_; }
+            void setBeaconMode(const std::string& mode); // Set the beacon mode.
+            const std::string& getBeaconMode(void) const; // Get the beacon mode.
+
+            /**
+            @brief Set the name a DistanceTriggerBeacon needs to have to make the DistanceTrigger react to it if in beacon-mode.
+            @param targetname The name as a string.
+            */
+            inline void setTargetName(const std::string& targetname)
+                { this->targetName_ = targetname; }
+            /**
+            @brief Get the target name.
+            @return Returns the target name as a string.
+            */
+            inline const std::string& getTargetName(void)
+                { return this->targetName_; }
+
+            bool checkDistance(); // Check, whether there are entities that are targets of this DistanceTrigger in its range.
+
+        protected:
+            virtual bool isTriggered(TriggerMode::Value mode); // Check whether the DistanceTrigger is triggered.
+            /**
+            @brief Notifies interested parties about a change of the DistanceTrigger's target mask.
+            */
+            virtual void notifyMaskUpdate() {}
+
+            ClassTreeMask targetMask_; //!< The target mask, specifies by which types of objects the DistanceTrigger can be triggered. 
+
+        private:
+            //! Strings for the beacon modes.
+            static const std::string beaconModeOff_s;
+            static const std::string beaconModeIdentify_s;
+            static const std::string beaconModeExlcude_s;
+
+            float distance_; //!< The range of the DistanceTrigger.
+            
+            distanceTriggerBeaconMode::Value beaconMode_; //!< The beacon mode.
+            std::string targetName_; //!< The name a DistanceTriggerBeacon needs to have to make the DistanceTrigger react to it if in beacon-mode.
+            ClassTreeMask* beaconMask_; //!< A mask, that only accepts DistanceTriggerBeacons.
+            
+            WeakPtr<WorldEntity> cache_; //!< Caches the entity that triggered the DistanceTrigger last.
+    };
 }
 
 #endif /* _DistanceTrigger_H__ */

Modified: code/trunk/src/modules/objects/triggers/EventMultiTrigger.h
===================================================================
--- code/trunk/src/modules/objects/triggers/EventMultiTrigger.h	2011-04-08 21:51:22 UTC (rev 8212)
+++ code/trunk/src/modules/objects/triggers/EventMultiTrigger.h	2011-04-09 13:33:06 UTC (rev 8213)
@@ -61,7 +61,7 @@
         @endcode
 
     @see MultiTrigger
-        For more information on MultiTriggers.
+        For more information on @ref orxonox::MultiTrigger "MultiTriggers".
 
     @author
         Damian 'Mozork' Frick

Modified: code/trunk/src/modules/objects/triggers/EventTrigger.cc
===================================================================
--- code/trunk/src/modules/objects/triggers/EventTrigger.cc	2011-04-08 21:51:22 UTC (rev 8212)
+++ code/trunk/src/modules/objects/triggers/EventTrigger.cc	2011-04-09 13:33:06 UTC (rev 8213)
@@ -41,6 +41,12 @@
 {
     CreateFactory(EventTrigger);
 
+    /**
+    @brief
+        Constructor. Registers and initializes the object.
+    @param creator
+        The creator of the EventTrigger.
+    */
     EventTrigger::EventTrigger(BaseObject* creator) : Trigger(creator)
     {
         RegisterObject(EventTrigger);
@@ -48,10 +54,18 @@
         this->bEventTriggered_ = false;
     }
 
+    /**
+    @brief
+        Destructor.
+    */
     EventTrigger::~EventTrigger()
     {
     }
 
+    /**
+    @brief
+        Creates an event port.
+    */
     void EventTrigger::XMLEventPort(Element& xmlelement, XMLPort::Mode mode)
     {
         SUPER(EventTrigger, XMLEventPort, xmlelement, mode);
@@ -59,6 +73,11 @@
         XMLPortEventState(EventTrigger, BaseObject, "trigger", trigger, xmlelement, mode);
     }
 
+    /**
+    @brief
+        Check whether the EventTrigger should be triggered.
+        It should be triggered if it is triggered according just to its sub-triggers and if the last event that came in was an event that changed from not triggered to triggered.
+    */
     bool EventTrigger::isTriggered(TriggerMode::Value mode)
     {
         if (Trigger::isTriggered(mode))

Modified: code/trunk/src/modules/objects/triggers/EventTrigger.h
===================================================================
--- code/trunk/src/modules/objects/triggers/EventTrigger.h	2011-04-08 21:51:22 UTC (rev 8212)
+++ code/trunk/src/modules/objects/triggers/EventTrigger.h	2011-04-09 13:33:06 UTC (rev 8213)
@@ -36,6 +36,7 @@
 #define _EventTrigger_H__
 
 #include "objects/ObjectsPrereqs.h"
+
 #include "Trigger.h"
 
 namespace orxonox
@@ -43,7 +44,23 @@
 
     /**
     @brief
+        The EventTrigger class provides a way to have a Trigger triggered by any kinds of @ref orxonox::Event "Events".
 
+        Example:
+        @code
+        <EventTrigger invert="true">
+            <events>
+                <trigger>
+                    <TriggerBase ... />
+                    <EventListener ... />
+                </trigger>
+            </events>
+        </EventTrigger>
+        @endcode
+
+    @see Trigger
+        For more information on @ref oroxnox::Trigger "Triggers".
+
     @author
         Fabian 'x3n' Landau
 
@@ -52,19 +69,24 @@
     class _ObjectsExport EventTrigger : public Trigger
     {
         public:
-            EventTrigger(BaseObject* creator);
+            EventTrigger(BaseObject* creator); // Constructor. Registers and initializes the object.
             virtual ~EventTrigger();
 
-            virtual void XMLEventPort(Element& xmlelement, XMLPort::Mode mode);
+            virtual void XMLEventPort(Element& xmlelement, XMLPort::Mode mode); // Creates an event port.
 
+            /**
+            @brief Method that is called when a new event comes in.
+                   The tick call makes sure the state change takes effect immediately.
+            @param bTriggered The state of the incoming event.
+            */
             inline void trigger(bool bTriggered)
                 { this->bEventTriggered_ = bTriggered; this->tick(0); }
 
         protected:
-            virtual bool isTriggered(TriggerMode::Value mode);
+            virtual bool isTriggered(TriggerMode::Value mode); // Check whether the EventTrigger should be triggered.
 
         private:
-            bool bEventTriggered_;
+            bool bEventTriggered_; //!< Boolean to keep track of what the state of the last event was.
     };
 }
 

Modified: code/trunk/src/modules/objects/triggers/MultiTrigger.cc
===================================================================
--- code/trunk/src/modules/objects/triggers/MultiTrigger.cc	2011-04-08 21:51:22 UTC (rev 8212)
+++ code/trunk/src/modules/objects/triggers/MultiTrigger.cc	2011-04-09 13:33:06 UTC (rev 8213)
@@ -91,7 +91,7 @@
 
         XMLPortParam(MultiTrigger, "simultaneousTriggerers", setSimultaneousTriggerers, getSimultaneousTriggerers, xmlelement, mode);
         XMLPortParam(MultiTrigger, "broadcast", setBroadcast, getBroadcast, xmlelement, mode);
-        XMLPortParamLoadOnly(MultiTrigger, "target", addTargets, xmlelement, mode).defaultValues("Pawn"); //TODO: Remove load only
+        XMLPortParamLoadOnly(MultiTrigger, "target", addTarget, xmlelement, mode).defaultValues("Pawn"); //TODO: Remove load only
 
         COUT(4) << "MultiTrigger '" << this->getName() << "' (&" << this << ") created." << std::endl;
     }
@@ -274,7 +274,7 @@
 
     /**
     @brief
-        Get whether the MultiTrigger is active for a given object.
+        Check whether the MultiTrigger is active for a given object.
     @param triggerer
         A pointer to the object.
     @return
@@ -292,9 +292,9 @@
     @brief
         Add some target to the MultiTrigger.
     @param targetStr
-        The target as a string.
+        The target class name as a string.
     */
-    void MultiTrigger::addTargets(const std::string& targetStr)
+    void MultiTrigger::addTarget(const std::string& targetStr)
     {
         Identifier* target = ClassByString(targetStr);
 
@@ -307,8 +307,8 @@
 
         this->targetMask_.include(target);
 
-        // A MultiTrigger shouldn't react to itself or other MultiTriggers.
-        this->targetMask_.exclude(Class(MultiTrigger), true);
+        // A MultiTrigger shouldn't react to itself or other triggers.
+        this->targetMask_.exclude(Class(TriggerBase), true);
 
         // We only want WorldEntities
         //TODO: Really?
@@ -323,7 +323,7 @@
     @param targetStr
         The target to be removed as a string.
     */
-    void MultiTrigger::removeTargets(const std::string& targetStr)
+    void MultiTrigger::removeTarget(const std::string& targetStr)
     {
         Identifier* target = ClassByString(targetStr);
 

Modified: code/trunk/src/modules/objects/triggers/MultiTrigger.h
===================================================================
--- code/trunk/src/modules/objects/triggers/MultiTrigger.h	2011-04-08 21:51:22 UTC (rev 8212)
+++ code/trunk/src/modules/objects/triggers/MultiTrigger.h	2011-04-09 13:33:06 UTC (rev 8213)
@@ -66,15 +66,15 @@
         In more detail: A Trigger is an object that can either be <em>active</em> or <em>inactive</em>, with a specified behavior how to switch between the two. A MultiTrigger generalizes that behavior for multiple objects triggering the trigger. A MultiTrigger can be <em>active</em> or <em>inactive</em> for any object triggering it, with the state for each object being completely independent of the state for other objects. Each time a switch occurs an @ref orxonox::Event "Event" is fired with as the originator a @ref orxonox::MultiTriggerContainer "MultiTriggerContainer", containing a pointer to the MultiTrigger that caused the @ref orxonox::Event "Event" and a pointer to the object that caused the trigger to change it's activity.
 
         MultiTriggers also allow for additional complexity which can be added through the choice of the parameters explained (briefly) below:
-        But first you must understand a small implementational detail. There is a distinction between the MultiTrigger being triggered (there is the state <em>triggered</em> for that) and the MultiTrigger being active (for that is the state <em>activity</em>). From the outside only the <em>activity</em> is visible. The state <em>triggered</em> tells us whether the trigger is actually triggered, but it could pretend (for some reason, some of which we will see shortly) to be triggered (or to the outside, active), while it in fact isn't. The standard behavior is, that the <em>activity</em> changes, when the MultiTrigger transits from being triggered to not being triggered or the other way around.
+        But first you must understand a small implementation detail. There is a distinction between the MultiTrigger being triggered (there is the state <em>triggered</em> for that) and the MultiTrigger being active (for that is the state <em>activity</em>). From the outside only the <em>activity</em> is visible. The state <em>triggered</em> tells us whether the trigger is actually triggered, but it could pretend (for some reason, some of which we will see shortly) to be <em>active</em>, while it in fact isn't. The standard behavior is, that the <em>activity</em> changes, when the MultiTrigger transits from being <em>triggered</em> to being <em>not triggered</em> or the other way around.
         The parameters are:
         - @b delay The delay is the time that the trigger waits until it reacts (i.e. changes it's state) to the triggering condition being fulfilled.
-        - @b switch Switch is a boolean, if true the MultiTrigger is in switch-mode, meaning, that the <em>activity</em> changes only when the trigger is triggered, this means, that now the <em>activity</em> only changes, when the trigger changes from not being triggered to being triggered but not the other way around. The default is false.
-        - @b stayactive Stay active is also a boolean, if true the MultiTrigger stays active after it has been activated as many times as specified by the parameter activations. The default is false.
-        - @b activations The number of activations until the trigger can't be triggered anymore. The default is -1, which is infinity.
-        - @b invert Invert is a boolean, if true the trigger is in <em>invert-mode</em>, meaning, that if the triggering condition is fulfilled the MultiTrigger will have the state not triggered and and if the condition is not fulfilled it will have the state triggered. In short it just inverts the behavior of the MultiTrigger. The default is false.
-        - @b simultaneousTriggerers The number of simultaneous triggerers limits the number of objects that are allowed to trigger the MultiTrigger at the same time. Or more precisely, the number of distinct objects the MultiTrigger has <em>triggered</em> states for, at each point in time. The default is -1, which denotes infinity.
-        - @b mode The mode describes how the MultiTrigger acts in relation to all the triggers, that are appended to it. There are 3 modes: <em>and</em>, meaning that the MultiTrigger can only be triggered if all the appended triggers are active. <em>or</em>, meaning that the MultiTrigger can only triggered if at least one of the appended triggers is active. And <em>xor</em>, meaning that the MultiTrigger can only be triggered if one and only one appended trigger is active. Note, that I wrote <em>can only be active</em>, that implies, that there is an additional condition to the activity of the MultiTrigger and that is the fulfillment of the triggering condition (the MultiTrigger itself doesn't have one, but all derived classes should). Also bear in mind, that the activity of a MultiTrigger is still coupled to the object that triggered it. The default is <em>and</em>.
+        - @b switch Switch is a boolean, if true the MultiTrigger is in <em>switch-mode</em>, meaning, that the <em>activity</em> changes only when the trigger is triggered, this means, that now the <em>activity</em> only changes, when the trigger changes from not being triggered to being triggered but not the other way around. The default is <code>false</code>.
+        - @b stayactive Stay active is also a boolean, if true the MultiTrigger stays active after it has been activated as many times as specified by the parameter <em>activations</em>. The default is <code>false</code>.
+        - @b activations The number of times the MultiTrigger can be activated until the trigger can't be triggered anymore. The default is <code>-1</code>, which denotes infinity.
+        - @b invert Invert is a boolean, if true the MultiTrigger is in <em>invert-mode</em>, meaning, that if the triggering condition is fulfilled the MultiTrigger will have the state <em>not triggered</em> and and if the condition is not fulfilled it will have the state <em>triggered</em>. In short it just inverts the behavior of the MultiTrigger. The default is <code>false</code>.
+        - @b simultaneousTriggerers The number of simultaneous triggerers limits the number of objects that are allowed to trigger the MultiTrigger at the same time. Or more precisely, the number of distinct objects the MultiTrigger has <em>triggered</em> states for, at each point in time. The default is <code>-1</code>, which denotes infinity.
+        - @b mode The mode describes how the MultiTrigger acts in relation to all the triggers, that are appended to it. There are 3 modes: <em>and</em>, meaning that the MultiTrigger can only be triggered if all the appended triggers are active. <em>or</em>, meaning that the MultiTrigger can only triggered if at least one of the appended triggers is active. And <em>xor</em>, meaning that the MultiTrigger can only be triggered if one and only one appended trigger is active. Note, that I wrote <em>can only be active</em>, that implies, that there is an additional condition to the <em>activity</em> of the MultiTrigger and that is the fulfillment of the triggering condition (the MultiTrigger itself doesn't have one, but all derived classes should). Also bear in mind, that the <em>activity</em> of a MultiTrigger is still coupled to the object that triggered it. The default is <em>and</em>.
         - @b broadcast Broadcast is a boolean, if true the MutliTrigger is in <em>broadcast-mode</em>, meaning, that all trigger events that are caused by no originator (originator is NULL) are broadcast as having come from every possible originator, or more precisely as having come from all objects that are specified targets of this MultiTrigger. The default is false.
         - @b target The target describes the kind of objects that are allowed to trigger this MultiTrigger. The default is @ref orxonox::Pawn "Pawn".
         - Also there is the possibility of appending triggers (as long as they inherit from TriggerBase) to the MultiTrigger just by adding them as children in the XML description of your MultiTrigger.
@@ -110,7 +110,7 @@
             */
             inline bool isActive(void) const
                 { return this->isActive(NULL); }
-            bool isActive(BaseObject* triggerer = NULL) const; //!< Get whether the MultiTrigger is active for a given object.
+            bool isActive(BaseObject* triggerer = NULL) const; //!< Check whether the MultiTrigger is active for a given object.
 
             /**
             @brief Set the number of objects that are allowed to simultaneously trigger this MultiTrigger.
@@ -157,8 +157,8 @@
             void fire(bool status, BaseObject* originator = NULL);  //!< Helper method. Creates an Event for the given status and originator and fires it.
             void broadcast(bool status); //!< Helper method. Broadcasts an Event for every object that is a target.
 
-            void addTargets(const std::string& targets); //!< Add some target to the MultiTrigger.
-            void removeTargets(const std::string& targets); //!< Remove some target from the MultiTrigger.
+            void addTarget(const std::string& targets); //!< Add some target to the MultiTrigger.
+            void removeTarget(const std::string& targets); //!< Remove some target from the MultiTrigger.
 
             /**
             @brief Get the target mask used to identify the targets of this MultiTrigger.

Modified: code/trunk/src/modules/objects/triggers/Trigger.cc
===================================================================
--- code/trunk/src/modules/objects/triggers/Trigger.cc	2011-04-08 21:51:22 UTC (rev 8212)
+++ code/trunk/src/modules/objects/triggers/Trigger.cc	2011-04-09 13:33:06 UTC (rev 8213)
@@ -38,237 +38,336 @@
 #include "core/GameMode.h"
 #include "core/XMLPort.h"
 #include "core/command/ConsoleCommand.h"
+
 #include "Scene.h"
 
 namespace orxonox
 {
 
-  SetConsoleCommand("Trigger", "debugFlares", &Trigger::debugFlares).defaultValues(false);
+    SetConsoleCommand("Trigger", "debugFlares", &Trigger::debugFlares).defaultValues(false);
 
-  CreateFactory(Trigger);
+    CreateFactory(Trigger);
 
-  Trigger::Trigger(BaseObject* creator) : TriggerBase(creator)
-  {
-    RegisterObject(Trigger);
+    /**
+    @brief
+        Constructor. Registers and initializes the object.
+    @param creator
+        The creator of the Trigger.
+    */
+    Trigger::Trigger(BaseObject* creator) : TriggerBase(creator)
+    {
+        RegisterObject(Trigger);
 
-    this->bActive_ = false;
-    this->bTriggered_ = false;
-    this->latestState_ = 0x0;
+        this->bActive_ = false;
+        this->bTriggered_ = false;
+        this->latestState_ = 0x0;
 
-    this->remainingTime_ = 0.0f;
-    this->timeSinceLastEvent_ = 0.0f;
+        this->remainingTime_ = 0.0f;
+        this->timeSinceLastEvent_ = 0.0f;
 
-//    this->bUpdating_ = false;
+        // Set the debug billboard.
+        if (this->getScene() && GameMode::showsGraphics())
+        {
+            this->debugBillboard_.setBillboardSet(this->getScene()->getSceneManager(), "Examples/Flare", ColourValue(1.0, 0.0, 0.0), 1);
+            this->debugBillboard_.setVisible(false);
 
-    if (this->getScene() && GameMode::showsGraphics())
-    {
-      this->debugBillboard_.setBillboardSet(this->getScene()->getSceneManager(), "Examples/Flare", ColourValue(1.0, 0.0, 0.0), 1);
-      this->debugBillboard_.setVisible(false);
+            if (this->debugBillboard_.getBillboardSet())
+                this->attachOgreObject(this->debugBillboard_.getBillboardSet());
+        }
 
-      if (this->debugBillboard_.getBillboardSet())
-          this->attachOgreObject(this->debugBillboard_.getBillboardSet());
+        this->setSyncMode(0x0);
     }
 
-    this->setSyncMode(0x0);
-  }
+    /**
+    @brief
+        Destructor.
+    */
+    Trigger::~Trigger()
+    {
 
-  Trigger::~Trigger()
-  {
-  }
+    }
 
-  void Trigger::XMLPort(Element& xmlelement, XMLPort::Mode mode)
-  {
-    SUPER(Trigger, XMLPort, xmlelement, mode);
-  }
-
-  void Trigger::tick(float dt)
-  {
-    if(this->bFirstTick_)
+    /**
+    @brief
+        Method for creating a Trigger object through XML.
+    */
+    void Trigger::XMLPort(Element& xmlelement, XMLPort::Mode mode)
     {
-      this->bFirstTick_ = false;
-      this->triggered(false);
+        SUPER(Trigger, XMLPort, xmlelement, mode);
     }
 
-    // Check if the object is active (this is NOT Trigger::isActive()!)
-    if (!this->BaseObject::isActive())
-        return;
+    /**
+    @brief
 
-    SUPER(Trigger, tick, dt);
+    @param dt
+        The time elapsed since last tick.
+    */
+    void Trigger::tick(float dt)
+    {
+        // If this is the first tick, announce, that the trigger is not triggered.
+        // This is needed, e.g. for an inverted trigger, that needs to announce at the beginning, that it is active.
+        if (this->bFirstTick_)
+        {
+            this->bFirstTick_ = false;
+            this->triggered(false);
+        }
 
-    bool newTriggered = this->isTriggered() ^ this->getInvert();
+        // Check if the object is active (this is NOT Trigger::isActive()!)
+        // If the object is not active we do nothing.
+        if (!this->BaseObject::isActive())
+            return;
 
-    // check if new triggering event is really new
-    if ((this->latestState_ & 0x1) != newTriggered)
-    {
-      // create new state
-      if (newTriggered)
-      {
-        this->latestState_ |= 1; // set trigger bit to 1
-        this->switchState();
-      }
-      else
-      {
-        this->latestState_ &= 0xFE; // set trigger bit to 0
-        if (!this->getSwitch())
-          this->switchState();
-      }
-    }
+        SUPER(Trigger, tick, dt);
 
-    if (this->remainingTime_ > 0.0)
-    {
-      this->remainingTime_ -= dt;
-      // only increase when acctually waiting for a state in the queue
-      if (this->timeSinceLastEvent_ >= 0.0)
-        this->timeSinceLastEvent_ += dt;
-    }
+        // Apply the invert operation.
+        bool newTriggered = this->isTriggered() ^ this->getInvert();
 
-    while (this->remainingTime_ <= 0.0 && this->stateChanges_.size() > 0)
-    {
-      // time ran out, change state to new one
-      char newState = this->stateChanges_.front().second;
-      this->bTriggered_ = (newState & 0x1);
-      this->bActive_ = newState & 2;
-      this->triggered(this->bActive_);
-      this->stateChanges_.pop();
-      if (this->stateChanges_.size() != 0)
-        this->remainingTime_ = this->stateChanges_.front().first;
-      else
-        this->timeSinceLastEvent_ = this->getDelay();
-    }
+        // Check if new triggering event is really new. (i.e. if the previous triggering state is not the same as the current)
+        if ((this->latestState_ & 0x1) != newTriggered)
+        {
+            // Create new state
+            if (newTriggered)
+            {
+                this->latestState_ |= 1; // Set triggered bit to 1.
+                this->switchState(); // Toggle the activity of the trigger.
+            }
+            else
+            {
+                this->latestState_ &= 0xFE; // Set triggered bit to 0.
+                // If this trigger is not in switched-mode (i.e. it switches its activity only if it changes from not triggered to triggered and not the other way around), the activity of the trigger is toggled.
+                if (!this->getSwitch())
+                    this->switchState();
+            }
+        }
 
-    if (this->bTriggered_ && this->bActive_)
-      this->setBillboardColour(ColourValue(0.5, 1.0, 0.0));
-    else if (!this->bTriggered_ && this->bActive_)
-      this->setBillboardColour(ColourValue(0.0, 1.0, 0.0));
-    else if (this->bTriggered_ && !this->bActive_)
-      this->setBillboardColour(ColourValue(1.0, 0.5, 0.0));
-    else
-      this->setBillboardColour(ColourValue(1.0, 0.0, 0.0));
-  }
+        // If there is time remaining, i.e. there are states in the queue waiting to take effect.
+        if (this->remainingTime_ > 0.0)
+        {
+            // Discount the last tick time from the time remaining.
+            this->remainingTime_ -= dt;
+            // Increase the time since the last event (the time since the last state took effect), but only when actually waiting for a state in the queue
+            if (this->timeSinceLastEvent_ >= 0.0)
+                this->timeSinceLastEvent_ += dt;
+        }
 
-  void Trigger::triggered(bool bIsTriggered)
-  {
-    this->fireEvent(bIsTriggered);
-  }
+        // If the remaining time has run out and there are states in the queue waiting to take effect.
+        while (this->remainingTime_ <= 0.0 && this->stateChanges_.size() > 0)
+        {
+            // Get the state to take effect and apply it.
+            char newState = this->stateChanges_.front().second;
+            this->bTriggered_ = (newState & 0x1);
+            this->bActive_ = newState & 0x2;
 
-  bool Trigger::isTriggered(TriggerMode::Value mode)
-  {
-//    if (this->bUpdating_)
-//      return this->bTriggered_;
+            // Fire a triggered (or un-triggered, depending on the activity) event.
+            this->triggered(this->bActive_);
 
-//    this->bUpdating_ = true;
-    if (this->children_.size() != 0)
-    {
-      bool returnval = false;
+            // Remove the state that was just applied from the queue.
+            this->stateChanges_.pop();
 
-      switch (mode)
-      {
-        case TriggerMode::EventTriggerAND:
-          returnval = checkAnd();
-          break;
-        case TriggerMode::EventTriggerOR:
-          returnval = checkOr();
-          break;
-        case TriggerMode::EventTriggerXOR:
-          returnval = checkXor();
-          break;
-        default:
-          returnval = false;
-          break;
-      }
-//      this->bUpdating_ = false;
+            // If there are still states in the queue, set the remaining time to the time of the next state to take effect.
+            if (this->stateChanges_.size() != 0)
+                this->remainingTime_ = this->stateChanges_.front().first;
+            // Else the time since the last event is set to the delay.
+            else
+                this->timeSinceLastEvent_ = this->getDelay();
+        }
 
-      return returnval;
+        // Set the color of the debug billboard according to the current state of the trigger.
+        if (this->bTriggered_ && this->bActive_)
+            this->setBillboardColour(ColourValue(0.5, 1.0, 0.0));
+        else if (!this->bTriggered_ && this->bActive_)
+            this->setBillboardColour(ColourValue(0.0, 1.0, 0.0));
+        else if (this->bTriggered_ && !this->bActive_)
+            this->setBillboardColour(ColourValue(1.0, 0.5, 0.0));
+        else
+            this->setBillboardColour(ColourValue(1.0, 0.0, 0.0));
     }
-    return true;
-  }
 
-  bool Trigger::checkAnd()
-  {
-    std::set<TriggerBase*>::iterator it;
-    for(it = this->children_.begin(); it != this->children_.end(); ++it)
+    /**
+    @brief
+        Fires an event with the input triggered state.
+    @param bIsTriggered
+        The triggered state.
+    */
+    void Trigger::triggered(bool bIsTriggered)
     {
-      if (!(*it)->isActive())
-        return false;
+        this->fireEvent(bIsTriggered);
     }
-    return true;
-  }
 
-  bool Trigger::checkOr()
-  {
-    std::set<TriggerBase*>::iterator it;
-    for(it = this->children_.begin(); it != this->children_.end(); ++it)
+    /**
+    @brief
+        Check whether the Trigger should be triggered, given only its sub-triggers, given a specific mode.
+    @param mode
+        The Trigger mode. Specifies how the sub-triggers are combined and how they affect the Trigger.
+    @return
+        Returns true if the Trigger should be triggered and false if not.
+    */
+    bool Trigger::isTriggered(TriggerMode::Value mode)
     {
-      if ((*it)->isActive())
+        // If the trigger has sub-triggers.
+        if (this->children_.size() > 0)
+        {
+            switch (mode)
+            {
+                case TriggerMode::EventTriggerAND:
+                    return checkAnd();
+                case TriggerMode::EventTriggerOR:
+                    return checkOr();
+                case TriggerMode::EventTriggerXOR:
+                    return checkXor();
+                default:
+                    return false;
+            }
+        }
+        // If the trigger has no sub-triggers, whether it is triggered should only depend on itself and nothing else, thus this returns true.
         return true;
     }
-    return false;
-  }
 
-  bool Trigger::checkXor()
-  {
-    std::set<TriggerBase*>::iterator it;
-    bool test = false;
-    for(it = this->children_.begin(); it != this->children_.end(); ++it)
+    /**
+    @brief
+        Check whether all the sub-triggers of this Trigger are active.
+        This is in fact the conjunction (logical AND) of the activity of all its sub-triggers.
+    @return
+        Returns true if all the sub-triggers of this Trigger are active, false if at least one of them is not active.
+    */
+    bool Trigger::checkAnd()
     {
-      if (test && (*it)->isActive())
+        // Iterate over all sub-triggers.
+        for (std::set<TriggerBase*>::iterator it = this->children_.begin(); it != this->children_.end(); ++it)
+        {
+            if (!(*it)->isActive())
+                return false;
+        }
+        return true;
+    }
+
+    /**
+    @brief
+        Check whether at least one of the sub-triggers of this Trigger is active.
+        This is in fact the disjunction (logical OR) of the activity of all its sub-triggers.
+    @return
+        Returns true if at least one of the sub-triggers of this Trigger is active, false if none of them is active.
+    */
+    bool Trigger::checkOr()
+    {
+        // Iterate over all sub-triggers.
+        for (std::set<TriggerBase*>::iterator it = this->children_.begin(); it != this->children_.end(); ++it)
+        {
+            if ((*it)->isActive())
+                return true;
+        }
         return false;
-      if ((*it)->isActive())
-        test = true;
     }
-    return test;
-  }
 
-  bool Trigger::switchState()
-  {
-    if (( (this->latestState_ & 2) && this->getStayActive() && (this->remainingActivations_ <= 0))
-     || (!(this->latestState_ & 2)                          && (this->remainingActivations_ == 0)))
-      return false;
-    else
+    /**
+    @brief
+        Check whether exactly one of the sub-triggers of this Trigger is active.
+        This is in fact the logical XOR of the activity of all its sub-triggers.
+    @return
+        Returns true if exactly one of the sub-triggers of this Trigger is active, false if none of them or two or more of them are active.
+    */
+    bool Trigger::checkXor()
     {
-      this->latestState_ ^= 2; // toggle state bit
+        bool test = false;
+        for (std::set<TriggerBase*>::iterator it = this->children_.begin(); it != this->children_.end(); ++it)
+        {
+            if (test && (*it)->isActive())
+                return false;
+            if ((*it)->isActive())
+                test = true;
+        }
+        return test;
+    }
 
-      // increase activation count
-      if (this->latestState_ & 2 && this->remainingActivations_ > 0)
-        this->remainingActivations_--;
+    /**
+    @brief
+        Switch (toggle) the activity of the Trigger.
+    @return
+        Returns true if the activity of the Trigger has changed. False if not.
+    */
+    bool Trigger::switchState()
+    {
+        // If the previous state was active and there are no remaining activations, but the trigger stays active.
+        // or if the previous state was inactive and there are no remaining activations.
+        // the activity is not switched.
+        if (( (this->latestState_ & 0x2) && this->getStayActive() && (this->remainingActivations_ <= 0))
+           || (!(this->latestState_ & 0x2)                        && (this->remainingActivations_ == 0)))
+            return false;
+        // Else the activity is switched.
+        else
+        {
+            this->latestState_ ^= 0x2; // Toggle activity bit.
 
-      this->storeState();
+            // If the activity has switched to active, decrease the remaining activations.
+            if (this->latestState_ & 0x2 && this->remainingActivations_ > 0)
+                this->remainingActivations_--;
 
-      return true;
+            // Store the new state in the queue.
+            this->storeState();
+
+            return true;
+        }
     }
-  }
 
-  void Trigger::storeState()
-  {
-    // put state change into queue
-    this->stateChanges_.push(std::pair<float, char>(this->timeSinceLastEvent_, this->latestState_));
-    // reset time since last event
-    this->timeSinceLastEvent_ = 0.0;
+    /**
+    @brief
+        Stores the state in the queue.
+        The queue is a list of states that are waiting to take effect paired with the time it has to wait after its preceding state takes effect.
+    */
+    void Trigger::storeState()
+    {
+        // Put the state change into the queue.
+        this->stateChanges_.push(std::pair<float, char>(this->timeSinceLastEvent_, this->latestState_));
+        // Reset time since last event
+        this->timeSinceLastEvent_ = 0.0;
 
-    if (this->stateChanges_.size() == 1)
-      this->remainingTime_ = this->stateChanges_.front().first;
-  }
+        // If there is just one state in the queue. (i.e. the one that we just added), The remaining time is set to the time it takes for the next state to take effect.
+        if (this->stateChanges_.size() == 1)
+            this->remainingTime_ = this->stateChanges_.front().first;
+    }
 
-  void Trigger::delayChanged(void)
-  {
-    this->timeSinceLastEvent_ = this->getDelay();
-  }
+    /**
+    @brief
+        React to a change in delay.
+        Only newly arriving states are affected by a change in delay.
+    */
+    void Trigger::delayChanged(void)
+    {
+        this->timeSinceLastEvent_ = this->getDelay();
+    }
 
-  void Trigger::debugFlares(bool bVisible)
-  {
-    for (ObjectList<Trigger>::iterator it = ObjectList<Trigger>::begin(); it != ObjectList<Trigger>::end(); ++it)
-      it->setVisible(bVisible);
-  }
+    /**
+    @brief
+        Set the visibility of all debug billboards of all Triggers.
+    @param bVisible
+        The visibility the billboards are set to.
+    */
+    void Trigger::debugFlares(bool bVisible)
+    {
+        // Iterate over all Triggers.
+        for (ObjectList<Trigger>::iterator it = ObjectList<Trigger>::begin(); it != ObjectList<Trigger>::end(); ++it)
+            it->setVisible(bVisible);
+    }
 
-  void Trigger::setBillboardColour(const ColourValue& colour)
-  {
-    this->debugBillboard_.setColour(colour);
-  }
+    /**
+    @brief
+        Set the colour of the debug billboard.
+    @param colour
+        The colour the billboard is set to.
+    */
+    void Trigger::setBillboardColour(const ColourValue& colour)
+    {
+        this->debugBillboard_.setColour(colour);
+    }
 
-  void Trigger::changedVisibility()
-  {
-    SUPER(Trigger, changedVisibility);
+    /**
+    @brief
+        React to a change of visibility of the trigger by adjusting the visibility of the debug billboards.
+    */
+    void Trigger::changedVisibility()
+    {
+        SUPER(Trigger, changedVisibility);
 
-    this->debugBillboard_.setVisible(this->isVisible());
-  }
+        this->debugBillboard_.setVisible(this->isVisible());
+    }
 }

Modified: code/trunk/src/modules/objects/triggers/Trigger.h
===================================================================
--- code/trunk/src/modules/objects/triggers/Trigger.h	2011-04-08 21:51:22 UTC (rev 8212)
+++ code/trunk/src/modules/objects/triggers/Trigger.h	2011-04-09 13:33:06 UTC (rev 8213)
@@ -47,60 +47,87 @@
 namespace orxonox
 {
 
-  /**
-  @brief
-    
-  @author
-    Benjamin Knecht
+    /**
+    @brief
+         A Trigger is an object that can either be <em>active</em> or <em>inactive</em>, with a specified behavior how to switch between the two. Each time a switch occurs an @ref orxonox::Event "Event" is fired with as the originator the Trigger that caused the @ref orxonox::Event "Event".
+         
+        Triggers also allow for additional complexity which can be added through the choice of the parameters explained below:
+        But first it is imperative to understand a small implementation detail. There is a distinction between the Trigger being triggered (there is the state <em>triggered</em> for that) and the Trigger being active (for that is the state <em>activity</em>). From the outside only the <em>activity</em> is visible. The state <em>triggered</em> tells us whether the trigger is actually triggered, but it could pretend (for some reason, some of which we will see shortly) to be <em>active</em>, while it in fact isn't. The standard behavior is, that the <em>activity</em> changes, when the Trigger transits from being <em>triggered</em> to being <em>not triggered</em> or the other way around.
+        The parameters are:
+        - @b delay The delay is the time that the trigger waits until it reacts (i.e. changes it's state) to the triggering condition being fulfilled.
+        - @b switch Switch is a boolean, if true the Trigger is in <em>switch-mode</em>, meaning, that the <em>activity</em> changes only when the trigger is triggered, this means, that now the <em>activity</em> only changes, when the trigger changes from not being triggered to being triggered but not the other way around. The default is <code>false</code>.
+        - @b stayactive Stay active is also a boolean, if true the Trigger stays active after it has been activated as many times as specified by the parameter <em>activations</em>. The default is <code>false</code>.
+        - @b activations The number of times the Trigger can be activated until the trigger can't be triggered anymore. The default is <code>-1</code>, which denotes infinity.
+        - @b invert Invert is a boolean, if true the Trigger is in <em>invert-mode</em>, meaning, that if the triggering condition is fulfilled the Trigger will have the state <em>not triggered</em> and and if the condition is not fulfilled it will have the state <em>triggered</em>. In short it just inverts the behavior of the Trigger. The default is <code>false</code>.
+        - @b mode The mode describes how the Trigger acts in relation to all the triggers, that are appended to it. There are 3 modes: <em>and</em>, meaning that the Trigger can only be triggered if all the appended triggers are active. <em>or</em>, meaning that the Trigger can only triggered if at least one of the appended triggers is active. And <em>xor</em>, meaning that the Trigger can only be triggered if one and only one appended trigger is active. Note, that I wrote <em>can only be active</em>, that implies, that there is an additional condition to the <em>activity</em> of the Trigger and that is the fulfillment of the triggering condition (the Trigger itself doesn't have one, but all derived classes should). Also bear in mind, that the <em>activity</em> of a Trigger is still coupled to the object that triggered it. The default is <em>and</em>.
+        - Also there is the possibility of appending triggers (as long as they inherit from TriggerBase) to the Trigger just by adding them as children in the XML description of your Trigger.
 
-  @ingroup NormalTrigger
-  */
-  class _ObjectsExport Trigger : public TriggerBase
-  {
-    public:
-      Trigger(BaseObject* creator);
-      virtual ~Trigger();
+        An example of a Trigger created through XML would look like this:
+        @code
+        <Trigger position="0,0,0" delay="1.3" switch="true" stayactive="true" activations="7" invert="true" mode="xor" broadcast="false" target="Pawn">
+            <TriggerBase />
+            ...
+            <TriggerBase />
+        </Trigger>
+        @endcode
 
-      virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode);
-      virtual void tick(float dt);
+    @author
+        Benjamin Knecht
 
-      inline bool isActive(void) const
-        { return this->bActive_; }
+    @ingroup NormalTrigger
+    */
+    class _ObjectsExport Trigger : public TriggerBase
+    {
+        public:
+            Trigger(BaseObject* creator); // Constructor. Registers and initializes the object.
+            virtual ~Trigger();
 
-      inline void setVisible(bool visibility)
-        { this->debugBillboard_.setVisible(visibility); }
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode); // Method for creating a Trigger object through XML.
+            virtual void tick(float dt);
 
-      void delayChanged(void);
+            /**
+            @brief Check whether the Trigger is active.
+            @return Returns if the Trigger is active.
+            */
+            inline bool isActive(void) const
+                { return this->bActive_; }
 
-      bool switchState();
+            void delayChanged(void); // React to a change in delay.
 
-      static void debugFlares(bool bVisible);
-      virtual void changedVisibility();
+            static void debugFlares(bool bVisible); // Set the visibility of all debug billboards of all Triggers.
+            virtual void changedVisibility(); // React to a change of visibility of the trigger by adjusting the visibility of the debug billboards.
 
-    protected:
-      inline bool isTriggered() { return this->isTriggered(this->mode_); }
-      virtual bool isTriggered(TriggerMode::Value mode);
-      virtual void triggered(bool bIsTriggered);
+        protected:
+            /**
+            @brief Check whether the Trigger is triggered according to its mode.
+            @return Returns true if the Trigger is triggered, false if not.
+            */
+            inline bool isTriggered()
+                { return this->isTriggered(this->mode_); }
+            virtual bool isTriggered(TriggerMode::Value mode); // Check whether the Trigger should be triggered, given only its sub-triggers, given a specific mode.
+            virtual void triggered(bool bIsTriggered); // Fires an event with the input triggered state.
 
-    private:
-      bool checkAnd();
-      bool checkOr();
-      bool checkXor();
-      void setBillboardColour(const ColourValue& colour);
-      void storeState();
+        private:
+            bool switchState(); // Switch (toggle) the activity (to the outside the triggered state) of the trigger.
+            void storeState(); // Stores the state in the queue.
+            
+            bool checkAnd(); // Check whether all the sub-triggers of this Trigger are active.
+            bool checkOr(); // Check whether at least one of the sub-triggers of this Trigger is active.
+            bool checkXor(); // Check whether exactly one of the sub-triggers of this Trigger is active.
+            
+            void setBillboardColour(const ColourValue& colour); // Set the colour of the debug billboard.
 
-      bool bActive_;
-      bool bTriggered_;
+            bool bActive_; //!< Whether the trigger is active (to the outside triggered).
+            bool bTriggered_; //!< Whether the trigger is triggered (to the inside).
 
-      char latestState_;
-      float remainingTime_;
-      float timeSinceLastEvent_;
+            char latestState_; //!< Temporarily stores a state consisting of whether the trigger is triggeres at the first bit (least significant bit) and its activity at the second bit.
+            float remainingTime_; //!< The time until the next state (in the queue) takes effect.
+            float timeSinceLastEvent_; //!< The time since the last event came in.
 
-//      bool bUpdating_;
-      BillboardSet debugBillboard_;
+            BillboardSet debugBillboard_; //!< A set of debug billboards to visualize the state of the trigger.
 
-      std::queue<std::pair<float, char> > stateChanges_;
-  };
+            std::queue<std::pair<float, char> > stateChanges_; //!< A queue of state changes (in the same format as latestState_) paired with the time they will take effect since the last state change took effect.
+    };
 
 }
 

Modified: code/trunk/src/modules/objects/triggers/TriggerBase.h
===================================================================
--- code/trunk/src/modules/objects/triggers/TriggerBase.h	2011-04-08 21:51:22 UTC (rev 8212)
+++ code/trunk/src/modules/objects/triggers/TriggerBase.h	2011-04-09 13:33:06 UTC (rev 8213)
@@ -63,7 +63,7 @@
 
     /**
     @brief
-        The TriggerBase class is a base class for the two types of triggers, the (normal) @ref orxonox::Trigger "Triggers" and the @ref orxonox::MultiTrigger "MultiTriggers", it encompasses the shared data and functionality between these two types of triggers, but is in itself not a trigger that has any meaningful behaviour and thus should not be instantiated.
+        The TriggerBase class is a base class for the two types of triggers, the (normal) @ref orxonox::Trigger "Triggers" and the @ref orxonox::MultiTrigger "MultiTriggers", it encompasses the shared data and functionality between these two types of triggers, but is in itself not a trigger that has any meaningful behavior and thus should not be instantiated.
 
     @author
         Damian 'Mozork' Frick
@@ -80,7 +80,7 @@
             virtual void tick(float dt); //!< A method that is executed each tick.
 
             /**
-            @brief Check whether the trigger is active.
+            @brief Check whether the trigger is active. (i.e. triggered to the outside)
             @return Returns if the trigger is active.
             */
             virtual bool isActive(void) const




More information about the Orxonox-commit mailing list