Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/dockingsystem2/src/modules/objects/triggers/DistanceTrigger.cc @ 9195

Last change on this file since 9195 was 8206, checked in by dafrick, 14 years ago

Extending DistanceTrigger (both the normal and the MultiTrigger version). DistanceTriggerBeacons, can now also be used to exclude specific objects from triggering a DistanceTrigger.
Beware: The syntax for the DistanceTrigger, used with a DistanceTriggerBeacon has changed.
It was: <DistanceTrigger target="DistanceTriggerBeacon" targetname="someBeacon" />
And is now: <DistanceTrigger target="WhateverTargetYouWantYourTriggerToReactTo" beaconMode="identify" targetname="someBeacon" />
Consult the documentation in DistanceMultiTrigger for it's specific usage, the DistanceTrigger works analogously.

  • Property svn:eol-style set to native
File size: 8.5 KB
RevLine 
[1693]1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Benjamin Knecht
24 *   Co-authors:
25 *      ...
26 *
27 */
28
[7601]29/**
30    @file DistanceTrigger.cc
31    @brief Implementation of the DistanceTrigger class.
32    @ingroup NormalTrigger
33*/
34
[1693]35#include "DistanceTrigger.h"
36
37#include "core/CoreIncludes.h"
38#include "core/XMLPort.h"
[5735]39#include "worldentities/pawns/Pawn.h"
[6906]40#include "DistanceTriggerBeacon.h"
[2261]41
[2071]42namespace orxonox
43{
[8206]44   
45  /*static*/ const std::string DistanceTrigger::beaconModeOff_s = "off";
46  /*static*/ const std::string DistanceTrigger::beaconModeIdentify_s = "identify";
47  /*static*/ const std::string DistanceTrigger::beaconModeExlcude_s = "exclude";
48   
[1693]49  CreateFactory(DistanceTrigger);
50
[8206]51  DistanceTrigger::DistanceTrigger(BaseObject* creator) : Trigger(creator), beaconMask_(NULL)
[1693]52  {
53    RegisterObject(DistanceTrigger);
54
[2029]55    this->distance_ = 100;
56    this->targetMask_.exclude(Class(BaseObject));
[8079]57    this->targetName_ = "";
[1693]58  }
59
60  DistanceTrigger::~DistanceTrigger()
61  {
[8206]62    if(this->beaconMask_ != NULL)
63      delete this->beaconMask_;
[1693]64  }
65
[2029]66  void DistanceTrigger::XMLPort(Element& xmlelement, XMLPort::Mode mode)
67  {
68    SUPER(DistanceTrigger, XMLPort, xmlelement, mode);
69
70    XMLPortParam(DistanceTrigger, "distance", setDistance, getDistance, xmlelement, mode).defaultValues(100.0f);
[6906]71    XMLPortParamLoadOnly(DistanceTrigger, "target", addTargets, xmlelement, mode).defaultValues("Pawn");
[8206]72    XMLPortParam(DistanceTrigger, "beaconMode", setBeaconMode, getBeaconMode, xmlelement, mode);
[6906]73    XMLPortParam(DistanceTrigger, "targetname", setTargetName, getTargetName, xmlelement, mode);
[2029]74  }
75
[1693]76  void DistanceTrigger::addTarget(Ogre::Node* targetNode)
77  {
78    this->targetSet_.insert(targetNode);
79  }
80
81  void DistanceTrigger::removeTarget(Ogre::Node* targetNode)
82  {
83    int returnval = this->targetSet_.erase(targetNode);
84    if (returnval == 0)
85    {
86      COUT(2) << "Warning: Node " << targetNode << " did not exist in targetSet of trigger " << this << " !" << std::endl;
87      COUT(4) << "Content of targetSet of trigger " << this << " :" << std::endl;
88      std::set<Ogre::Node*>::iterator it;
[2029]89      for (it = this->targetSet_.begin(); it != this->targetSet_.end(); ++it)
[1693]90      {
91        COUT(4) << *it << std::endl;
92      }
93      COUT(4) << "End of targetSet of trigger " << this << std::endl;
94    }
95  }
96
[1969]97  void DistanceTrigger::addTargets(const std::string& targets)
[1693]98  {
[1961]99    Identifier* targetId = ClassByString(targets);
[3034]100
[2261]101    //! Checks whether the target is (or is derived from) a ControllableEntity.
[6906]102    Identifier* pawnId = Class(Pawn);
103    Identifier* distanceTriggerBeaconId = Class(DistanceTriggerBeacon);
104    if(targetId->isA(pawnId) || targetId->isA(distanceTriggerBeaconId))
[2261]105    {
106      this->setForPlayer(true);
107    }
[3034]108
[2069]109    if (!targetId)
[2071]110    {
[6417]111        COUT(1) << "Error: \"" << targets << "\" is not a valid class name to include in ClassTreeMask (in " << this->getName() << ", class " << this->getIdentifier()->getName() << ')' << std::endl;
[2069]112        return;
[2071]113    }
[2069]114
115    this->targetMask_.include(targetId);
116
[1693]117    // trigger shouldn't react on itself or other triggers
[2069]118    this->targetMask_.exclude(Class(Trigger), true);
[1693]119
[2069]120    // we only want WorldEntities
121    ClassTreeMask WEMask;
122    WEMask.include(Class(WorldEntity));
123    this->targetMask_ *= WEMask;
[3033]124
125    this->notifyMaskUpdate();
[1693]126  }
127
[1969]128  void DistanceTrigger::removeTargets(const std::string& targets)
[1693]129  {
[1961]130    Identifier* targetId = ClassByString(targets);
[2069]131    this->targetMask_.exclude(targetId);
[1693]132  }
133
134  bool DistanceTrigger::checkDistance()
135  {
[8206]136    // Check for new objects that are in range
137    ClassTreeMask targetMask = this->targetMask_;
138    if(this->beaconMode_ == distanceTriggerBeaconMode::identify)
139     targetMask = *this->beaconMask_;
140   
[2069]141    // Iterate through all objects
[8206]142    for (ClassTreeMaskObjectIterator it = targetMask.begin(); it != targetMask.end(); ++it)
[1693]143    {
[3325]144      WorldEntity* entity = orxonox_cast<WorldEntity*>(*it);
[2069]145      if (!entity)
146        continue;
[8206]147     
148       // If the DistanceTrigger is in identify mode and the DistanceTriggerBeacon attached to the object has the wrong name we ignore it.
149      if(this->beaconMode_ == distanceTriggerBeaconMode::identify)
[6906]150      {
[8206]151        if(entity->getName() != this->targetName_)
152            continue;
153        // If the object, the DistanceTriggerBeacon is attached to, is not a target of this DistanceMultiTrigger.
154        else if(this->targetMask_.isExcluded(entity->getParent()->getIdentifier()))
155            continue;
156      }
157   
158      // If the DistanceTrigger is in exclude mode and the DistanceTriggerBeacon attached to the object has the right name, we ignore it.
159      if(this->beaconMode_ == distanceTriggerBeaconMode::exclude)
160      {
161       
162        const std::set<WorldEntity*> attached = entity->getAttachedObjects();
163        bool found = false;
164        for(std::set<WorldEntity*>::const_iterator it = attached.begin(); it != attached.end(); it++)
[7301]165        {
[8206]166          if((*it)->isA(ClassIdentifier<DistanceTriggerBeacon>::getIdentifier()) && static_cast<DistanceTriggerBeacon*>(*it)->getName() == this->targetName_)
167          {
168            found = true;
169            break;
170          }
[7301]171        }
[8206]172        if(found)
[6906]173          continue;
174      }
[7163]175
[2069]176      Vector3 distanceVec = entity->getWorldPosition() - this->getWorldPosition();
177      if (distanceVec.length() < this->distance_)
[2261]178      {
[3034]179
[8206]180        // If the target is a player (resp. is a, or is derived from a, Pawn) the triggeringPlayer is set to the target entity.
[2261]181        if(this->isForPlayer())
[3034]182        {
[6906]183
[8206]184          // Change the entity to the parent of the DistanceTriggerBeacon (if in identify-mode), which is the entity to which the beacon is attached.
185          if(this->beaconMode_ == distanceTriggerBeaconMode::identify)
[6906]186            entity = entity->getParent();
187
[3325]188          Pawn* player = orxonox_cast<Pawn*>(entity);
[3034]189          this->setTriggeringPlayer(player);
190        }
191
[2069]192        return true;
[2261]193      }
[1693]194    }
[7163]195
[1693]196    return false;
197  }
[8206]198 
199  /**
200  @brief
201    Set the beacon mode.
202  @param mode
203    The mode as an enum.
204  */
205  void DistanceTrigger::setBeaconModeDirect(distanceTriggerBeaconMode::Value mode)
206  {
207    this->beaconMode_ = mode;
208    if(this->beaconMode_ == distanceTriggerBeaconMode::identify && this->beaconMask_ == NULL)
209    {
210      this->beaconMask_ = new ClassTreeMask();
211      this->beaconMask_->exclude(Class(BaseObject));
212      this->beaconMask_->include(Class(DistanceTriggerBeacon));
213    }
214  }
215   
216  /**
217  @brief
218    Get the beacon mode.
219  @return
220    Returns the mode as a string.
221  */
222  const std::string& DistanceTrigger::getBeaconMode(void) const
223  {
224    switch(this->getBeaconModeDirect())
225    {
226      case distanceTriggerBeaconMode::off :
227        return DistanceTrigger::beaconModeOff_s;
228      case distanceTriggerBeaconMode::identify:
229        return DistanceTrigger::beaconModeIdentify_s;
230      case distanceTriggerBeaconMode::exclude:
231        return DistanceTrigger::beaconModeExlcude_s;
232      default :
233        assert(0); // This is impossible.
234        return BLANKSTRING;
235    }
236  }
237   
238  /**
239  @brief
240    Set the beacon mode.
241  @param mode
242    The mode as a string.
243  */
244  void DistanceTrigger::setBeaconMode(const std::string& mode)
245  {
246    if(mode == DistanceTrigger::beaconModeOff_s)
247      this->setBeaconModeDirect(distanceTriggerBeaconMode::off);
248    else if(mode == DistanceTrigger::beaconModeIdentify_s)
249      this->setBeaconModeDirect(distanceTriggerBeaconMode::identify);
250    else if(mode == DistanceTrigger::beaconModeExlcude_s)
251      this->setBeaconModeDirect(distanceTriggerBeaconMode::exclude);
252    else
253      COUT(1) << "Invalid beacon mode in DistanceTrigger." << endl;
254  }
[1693]255
[3280]256  bool DistanceTrigger::isTriggered(TriggerMode::Value mode)
[1693]257  {
[2029]258    if (Trigger::isTriggered(mode))
[2261]259    {
[1693]260      return checkDistance();
[2261]261    }
[1693]262    else
263      return false;
264  }
265}
Note: See TracBrowser for help on using the repository browser.