Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/tutorial6/src/modules/objects/triggers/DistanceTrigger.cc @ 11133

Last change on this file since 11133 was 11099, checked in by muemart, 9 years ago

Fix loads of doxygen warnings and other documentation issues

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