Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/modules/objects/triggers/DistanceTrigger.cc @ 10532

Last change on this file since 10532 was 9667, checked in by landauf, 11 years ago

merged core6 back to trunk

  • Property svn:eol-style set to native
File size: 10.4 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"
[8213]39
[5735]40#include "worldentities/pawns/Pawn.h"
[8213]41
[6906]42#include "DistanceTriggerBeacon.h"
[2261]43
[2071]44namespace orxonox
45{
[1693]46
[8213]47    /*static*/ const std::string DistanceTrigger::beaconModeOff_s = "off";
48    /*static*/ const std::string DistanceTrigger::beaconModeIdentify_s = "identify";
49    /*static*/ const std::string DistanceTrigger::beaconModeExlcude_s = "exclude";
[1693]50
[9667]51    RegisterClass(DistanceTrigger);
[1693]52
[8213]53    /**
54    @brief
55        Constructor. Registers and initializes the object.
56    @param creator
57        The creator of this trigger.
58    */
[9667]59    DistanceTrigger::DistanceTrigger(Context* context) : Trigger(context)
[8213]60    {
61        RegisterObject(DistanceTrigger);
[1693]62
[8213]63        this->distance_ = 100;
64        this->targetMask_.exclude(Class(BaseObject));
65        this->targetName_ = "";
[8706]66        this->beaconMask_.exclude(Class(BaseObject));
67        this->beaconMask_.include(Class(DistanceTriggerBeacon));
[8213]68    }
[2029]69
[8213]70    /**
71    @brief
72        Destructor.
73    */
74    DistanceTrigger::~DistanceTrigger()
[1693]75    {
[8706]76
[1693]77    }
78
[8213]79    /**
80    @brief
81        Method for creating a DistanceTrigger object through XML.
82    */
83    void DistanceTrigger::XMLPort(Element& xmlelement, XMLPort::Mode mode)
84    {
85        SUPER(DistanceTrigger, XMLPort, xmlelement, mode);
[3034]86
[8213]87        XMLPortParam(DistanceTrigger, "distance", setDistance, getDistance, xmlelement, mode).defaultValues(100.0f);
88        XMLPortParamLoadOnly(DistanceTrigger, "target", addTarget, xmlelement, mode).defaultValues("Pawn");
89        XMLPortParam(DistanceTrigger, "beaconMode", setBeaconMode, getBeaconMode, xmlelement, mode);
90        XMLPortParam(DistanceTrigger, "targetname", setTargetName, getTargetName, xmlelement, mode);
[2261]91    }
[3034]92
[8213]93    /**
94    @brief
95        Add some target to the DistanceTrigger.
96    @param targetStr
97        The target class name as a string.
98    */
99    void DistanceTrigger::addTarget(const std::string& targetStr)
[2071]100    {
[8213]101        Identifier* targetId = ClassByString(targetStr);
[2069]102
[8213]103        // 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.
104        Identifier* pawnId = Class(Pawn);
105        if(targetId->isA(pawnId))
106            this->setForPlayer(true);
[2069]107
[8213]108        if (targetId == NULL)
109        {
[8858]110            orxout(internal_error, context::triggers) << "\"" << targetStr << "\" is not a valid class name to include in ClassTreeMask (in " << this->getName() << ", class " << this->getIdentifier()->getName() << ')' << endl;
[8213]111            return;
112        }
[1693]113
[8213]114        // Add the target to the target mask.
115        this->targetMask_.include(targetId);
[3033]116
[8213]117        // The DistanceTrigger shouldn't react to itself or other triggers.
118        this->targetMask_.exclude(Class(TriggerBase), true);
[1693]119
[8213]120        // We only want WorldEntities (since only they have a position)
121        ClassTreeMask WEMask;
122        WEMask.include(Class(WorldEntity));
123        this->targetMask_ *= WEMask;
[1693]124
[8213]125        this->notifyMaskUpdate(); // Inform interested parties that the target mask has been updated.
126    }
127
128    /**
129    @brief
130        Remove some target from the DistanceTrigger.
131    @param targetStr
132        The target class name as a string.
133    */
134    void DistanceTrigger::removeTarget(const std::string& targetStr)
[1693]135    {
[8213]136        Identifier* targetId = ClassByString(targetStr);
137        this->targetMask_.exclude(targetId);
138    }
[2069]139
[8213]140    /**
141    @brief
142        Check, whether there are entities that are targets of this DistanceTrigger in its range.
143    @return
144        Returns true if there are valid entities in its range.
145    */
146    bool DistanceTrigger::checkDistance()
147    {
148        // 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.
149        if(this->cache_.get() != NULL)
[7301]150        {
[8213]151            if((this->cache_.get()->getWorldPosition() - this->getWorldPosition()).length() < this->distance_)
152                return true;
153            else
154                this->cache_.reset();
[7301]155        }
[8213]156       
157        // Check for new objects that are in range
158        ClassTreeMask targetMask = this->targetMask_;
159        // If we are in identify-mode another target mask has to be applies to find the DistanceTriggerBeacons.
160        if(this->beaconMode_ == distanceTriggerBeaconMode::identify)
[8706]161            targetMask = this->beaconMask_;
[7163]162
[8213]163        // Iterate through all objects that are targets of the DistanceTrigger.
164        for (ClassTreeMaskObjectIterator it = targetMask.begin(); it != targetMask.end(); ++it)
[3034]165        {
[8213]166            WorldEntity* entity = static_cast<WorldEntity*>(*it);
[6906]167
[8213]168            // If the DistanceTrigger is in identify-mode and the DistanceTriggerBeacon attached to the object has the wrong name we ignore it.
169            if(this->beaconMode_ == distanceTriggerBeaconMode::identify)
170            {
171                if(entity->getName() != this->targetName_)
172                    continue;
173                // If the object, the DistanceTriggerBeacon is attached to, is not a target of this DistanceMultiTrigger.
174                else if(this->targetMask_.isExcluded(entity->getParent()->getIdentifier()))
175                    continue;
176            }
[6906]177
[8213]178            // If the DistanceTrigger is in exclude mode and the DistanceTriggerBeacon attached to the object has the right name, we ignore it.
179            if(this->beaconMode_ == distanceTriggerBeaconMode::exclude)
180            {
181
182                const std::set<WorldEntity*> attached = entity->getAttachedObjects();
183                bool found = false;
184                for(std::set<WorldEntity*>::const_iterator it = attached.begin(); it != attached.end(); it++)
185                {
186                    if((*it)->isA(ClassIdentifier<DistanceTriggerBeacon>::getIdentifier()) && static_cast<DistanceTriggerBeacon*>(*it)->getName() == this->targetName_)
187                    {
188                        found = true;
189                        break;
190                    }
191                }
192                if(found)
193                    continue;
194            }
195
196            // Check if the entity is in range.
197            Vector3 distanceVec = entity->getWorldPosition() - this->getWorldPosition();
198            if (distanceVec.length() < this->distance_)
199            {
200                // If the target is a player (resp. is a, or is derived from a, Pawn) the triggeringPlayer is set to the target entity.
201                if(this->isForPlayer())
202                {
203                    // Change the entity to the parent of the DistanceTriggerBeacon (if in identify-mode), which is the entity to which the beacon is attached.
204                    if(this->beaconMode_ == distanceTriggerBeaconMode::identify)
205                        entity = entity->getParent();
206
[8706]207                    Pawn* pawn = orxonox_cast<Pawn*>(entity);
208                    if(pawn != NULL)
209                        this->setTriggeringPawn(pawn);
210                    else
[8858]211                        orxout(internal_warning, context::triggers) << "Pawn was NULL." << endl;
[8213]212                }
213               
214                // Add the entity to the cache.
215                this->cache_ = WeakPtr<WorldEntity>(entity);
216
217                return true;
218            }
[3034]219        }
220
[8213]221        return false;
[1693]222    }
[7163]223
[8213]224    /**
225    @brief
226        Set the beacon mode.
227    @param mode
228        The mode as an enum.
229    */
230    void DistanceTrigger::setBeaconModeDirect(distanceTriggerBeaconMode::Value mode)
231    {
232        this->beaconMode_ = mode;
233    }
[1693]234
[8213]235    /**
236    @brief
237        Get the beacon mode.
238    @return
239        Returns the mode as a string.
240    */
241    const std::string& DistanceTrigger::getBeaconMode(void) const
[2261]242    {
[8213]243        switch(this->getBeaconModeDirect())
244        {
245            case distanceTriggerBeaconMode::off :
246                return DistanceTrigger::beaconModeOff_s;
247            case distanceTriggerBeaconMode::identify:
248                return DistanceTrigger::beaconModeIdentify_s;
249            case distanceTriggerBeaconMode::exclude:
250                return DistanceTrigger::beaconModeExlcude_s;
251            default :
252                assert(0); // This is impossible.
253                return BLANKSTRING;
254        }
[2261]255    }
[8213]256
257    /**
258    @brief
259        Set the beacon mode.
260    @param mode
261        The mode as a string.
262    */
263    void DistanceTrigger::setBeaconMode(const std::string& mode)
264    {
265        if(mode == DistanceTrigger::beaconModeOff_s)
266            this->setBeaconModeDirect(distanceTriggerBeaconMode::off);
267        else if(mode == DistanceTrigger::beaconModeIdentify_s)
268            this->setBeaconModeDirect(distanceTriggerBeaconMode::identify);
269        else if(mode == DistanceTrigger::beaconModeExlcude_s)
270            this->setBeaconModeDirect(distanceTriggerBeaconMode::exclude);
271        else
[8858]272            orxout(internal_error, context::triggers) << "Invalid beacon mode in DistanceTrigger." << endl;
[8213]273    }
274
275    /**
276    @brief
277        Check whether the DistanceTrigger is triggered.
278        It is triggered if it is triggered according only to its mode (i.e. its sub-triggers) and if a target is in range.
[8706]279    @param mode
280        The mode for which it is tested, whether the DistanceTrigger is triggered.
281    @return
[8213]282        Returns true if it is triggered ,false if not.
283    */
284    bool DistanceTrigger::isTriggered(TriggerMode::Value mode)
285    {
286        if (Trigger::isTriggered(mode))
287            return checkDistance();
288        else
289            return false;
290    }
[1693]291}
Note: See TracBrowser for help on using the repository browser.