Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/modules/objects/triggers/DistanceMultiTrigger.cc @ 6861

Last change on this file since 6861 was 6860, checked in by dafrick, 15 years ago

Resolved bug in DistanceMultiTrigger, that caused a segfault, when an object in range of the trigger was destroyed.

File size: 4.9 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 *      Damian 'Mozork' Frick
24 *   Co-authors:
25 *      ...
26 *
27*/
28
29/**
30    @file DistanceMultiTrigger.cc
31    @brief Implementation of the DistanceMultiTrigger class.
32*/
33
34#include "DistanceMultiTrigger.h"
35
36#include "core/CoreIncludes.h"
37#include "core/XMLPort.h"
38
39namespace orxonox
40{
41   
42    CreateFactory(DistanceMultiTrigger);
43
44    /**
45    @brief
46        Default Constructor. Registers the object and initializes default values.
47    */
48    DistanceMultiTrigger::DistanceMultiTrigger(BaseObject* creator) : MultiTrigger(creator)
49    {
50        RegisterObject(DistanceMultiTrigger);
51       
52        this->distance_ = 100.0f;
53    }
54
55    /**
56    @brief
57        Destructor.
58    */
59    DistanceMultiTrigger::~DistanceMultiTrigger()
60    {
61       
62    }
63
64    /**
65    @brief
66        Method for creating a DistanceMultiTrigger object through XML.
67    */
68    void DistanceMultiTrigger::XMLPort(Element& xmlelement, XMLPort::Mode mode)
69    {
70        SUPER(DistanceMultiTrigger, XMLPort, xmlelement, mode);
71
72        XMLPortParam(DistanceMultiTrigger, "distance", setDistance, getDistance, xmlelement, mode);
73    }
74
75    /**
76    @brief
77        This method is called by the MultiTrigger to get information about new trigger events that need to be looked at.
78
79        In this implementation we iterate through all possible objects and check whether the fact that they are in range or not has changed and fire and hand a state ofer to the MultiTrigger if so.
80    */
81    std::queue<MultiTriggerState*>* DistanceMultiTrigger::letTrigger(void)
82    {
83        ClassTreeMask& targetMask = this->getTargetMask();
84
85        std::queue<MultiTriggerState*>* queue = NULL;
86
87        // Check for objects that were in range but no longer are. Iterate through all objects, that are in range.
88        for(std::map<WorldEntity*, WeakPtr<WorldEntity>* >::iterator it = this->range_.begin(); it != this->range_.end(); )
89        {
90            WorldEntity* entity = it->second->get();
91            WorldEntity* key = it->first;
92            if(entity == NULL)
93            {
94                it++;
95                this->removeFromRange(key);
96                continue;
97            }
98           
99            Vector3 distanceVec = entity->getWorldPosition() - this->getWorldPosition();
100            // If the object is no longer in range.
101            if (distanceVec.length() > this->distance_)
102            {
103                if(!this->removeFromRange(entity))
104                    continue;
105
106                // If no queue has been created, yet.
107                if(queue == NULL)
108                    queue = new std::queue<MultiTriggerState*>();
109
110                // Create a state and append it to the queue.
111                MultiTriggerState* state = new MultiTriggerState;
112                state->bTriggered = false;
113                state->originator = entity;
114                queue->push(state);
115            }
116            else
117                ++it;
118        }
119
120        // Check for new objects that are in range
121        for(ClassTreeMaskObjectIterator it = targetMask.begin(); it != targetMask.end(); ++it)
122        {
123            WorldEntity* entity = static_cast<WorldEntity*>(*it);
124            if (entity == NULL) //If the object is no WorldEntity or is already in range.
125                continue;
126
127            Vector3 distanceVec = entity->getWorldPosition() - this->getWorldPosition();
128            // If the object is in range.
129            if (distanceVec.length() <= this->distance_)
130            {
131                // Add the object to the objects that are in range.
132                if(!this->addToRange(entity))
133                    continue;
134
135                // If no queue has been created, yet.
136                if(queue == NULL)
137                    queue = new std::queue<MultiTriggerState*>();
138
139                // Create a state and append it to the queue.
140                MultiTriggerState* state = new MultiTriggerState;
141                state->bTriggered = true;
142                state->originator = entity;
143                queue->push(state);
144            }
145        }
146       
147        return queue;
148    }
149   
150}
Note: See TracBrowser for help on using the repository browser.