Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/presentation2012merge/src/modules/pickup/PickupCollection.cc @ 9290

Last change on this file since 9290 was 9290, checked in by landauf, 12 years ago

Fixed crash with MSVC if a PickupCollection was used
A depleted CollectiblePickup is now destroyed instead of being dropped
A destroyed CollectiblePickup removes itself from the PickupCollection
PickupCollection has to use a list instead of a vector because of this reason
Also PickupCollectionIdentifier needed to be changed because the number of pickups in a collection may now change
Probably also fixed a bug in PickupCollectionIdentifier::compare() because it2 was not incremented

not completely clean yet

  • Property svn:eol-style set to native
File size: 11.8 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 PickupCollection.cc
31    @brief Implementation of PickupCollection.
32*/
33
34#include "core/CoreIncludes.h"
35#include "core/XMLPort.h"
36
37#include "interfaces/PickupCarrier.h"
38
39#include "CollectiblePickup.h"
40#include "DroppedPickup.h"
41#include "PickupCollectionIdentifier.h"
42
43#include "PickupCollection.h"
44
45namespace orxonox
46{
47
48    CreateFactory(PickupCollection);
49
50    /**
51    @brief
52        Default Constructor.
53    @param creator
54        The creator of the object.
55    */
56    PickupCollection::PickupCollection(BaseObject* creator) : BaseObject(creator), pickupCollectionIdentifier_(NULL)
57    {
58        RegisterObject(PickupCollection);
59
60        this->pickupCollectionIdentifier_ = new PickupCollectionIdentifier(this);
61        this->usedCounter_ = 0;
62        this->pickedUpCounter_ = 0;
63        this->disabledCounter_ = 0;
64        this->processingUsed_ = false;
65        this->processingPickedUp_ = false;
66    }
67
68    /**
69    @brief
70        Destructor. Iterates through all Pickupables this PickupCollection consists of and destroys them if they haven't been already.
71    */
72    PickupCollection::~PickupCollection()
73    {
74        // Destroy all Pickupables constructing this PickupCollection.
75        for(std::list<CollectiblePickup*>::iterator it = this->pickups_.begin(); it != this->pickups_.end(); ++it)
76        {
77            (*it)->wasRemovedFromCollection();
78            (*it)->destroyPickup();
79        }
80        this->pickups_.clear();
81
82        if(this->pickupCollectionIdentifier_ != NULL)
83            delete this->pickupCollectionIdentifier_;
84    }
85
86    /**
87    @brief
88        Creates an instance of this Class through XML.
89    */
90    void PickupCollection::XMLPort(Element& xmlelement, XMLPort::Mode mode)
91    {
92        SUPER(PickupCollection, XMLPort, xmlelement, mode);
93
94        XMLPortObject(PickupCollection, CollectiblePickup, "pickupables", addPickupable, getPickupable, xmlelement, mode);
95    }
96
97    /**
98    @brief
99        Is called when the pickup has transited from used to unused or the other way around.
100        Any Class overwriting this method must call its SUPER function by adding SUPER(Classname, changedUsed); to their changdeUsed method.
101    */
102    void PickupCollection::changedUsed(void)
103    {
104        SUPER(PickupCollection, changedUsed);
105
106        this->processingUsed_ = true;
107        // Change used for all Pickupables this PickupCollection consists of.
108        for(std::list<CollectiblePickup*>::iterator it = this->pickups_.begin(); it != this->pickups_.end(); ++it)
109            (*it)->setUsed(this->isUsed());
110
111        this->processingUsed_ = false;
112
113        this->changedUsedAction();
114    }
115
116    /**
117    @brief
118        Helper method.
119        Checks whether due to changes in the used status of the pickups of this PickupCollection the used status of this PickupCollection has to change as well.
120    */
121    void PickupCollection::changedUsedAction(void)
122    {
123        if(this->processingUsed_)
124            return;
125
126        // If all the pickups are not in use but the PickupCollection is.
127        if(this->usedCounter_ == 0 && this->isUsed())
128            this->setUsed(false);
129
130        // If all the enabled pickups are in use but the PickupCollection is not.
131        if(this->usedCounter_ != 0 && this->usedCounter_ == this->pickups_.size()-this->disabledCounter_ && !this->isUsed())
132            this->setUsed(true);
133    }
134
135    /**
136    @brief
137        Is called when the pickup has changed its PickupCarrier.
138        Any Class overwriting this method must call its SUPER function by adding SUPER(Classname, changedCarrier); to their changedCarrier method.
139    */
140    void PickupCollection::changedCarrier(void)
141    {
142        SUPER(PickupCollection, changedCarrier);
143
144        // Change the PickupCarrier for all Pickupables this PickupCollection consists of.
145        for(std::list<CollectiblePickup*>::iterator it = this->pickups_.begin(); it != this->pickups_.end(); ++it)
146        {
147            if(this->getCarrier() == NULL)
148                (*it)->setCarrier(NULL);
149            else
150                (*it)->setCarrier(this->getCarrier()->getTarget(*it));
151        }
152    }
153
154    /**
155    @brief
156        Is called when the pickup has transited from picked up to dropped or the other way around.
157        Any Class overwriting this method must call its SUPER function by adding SUPER(Classname, changedPickedUp); to their changedPickedUp method.
158    */
159    void PickupCollection::changedPickedUp()
160    {
161        SUPER(PickupCollection, changedPickedUp);
162
163        this->processingPickedUp_ = true;
164        // Change the pickedUp status for all Pickupables this PickupCollection consists of.
165        for(std::list<CollectiblePickup*>::iterator it = this->pickups_.begin(); it != this->pickups_.end(); )
166            (*(it++))->setPickedUp(this->isPickedUp());
167
168        this->processingPickedUp_ = false;
169
170        this->changedPickedUpAction();
171    }
172
173    /**
174    @brief
175        Helper method.
176        Checks whether due to changes in the picked up status of the pickups of this PickupCollection the picked up status of this PickupCollection has to change as well.
177    */
178    void PickupCollection::changedPickedUpAction(void)
179    {
180        if(this->processingPickedUp_)
181            return;
182
183        // If at least all the enabled pickups of this PickupCollection are no longer picked up.
184        if(this->pickedUpCounter_ <= this->disabledCounter_ && this->isPickedUp())
185            this->Pickupable::destroy();
186
187        // If the PickupCollection is no longer picked up.
188        if(!this->isPickedUp())
189            this->pickedUpCounter_ = 0;
190    }
191
192    /**
193    @brief
194        Creates a duplicate of the input Pickupable.
195        This method needs to be implemented by any Class inheriting from Pickupable.
196    @param item
197        A reference to a pointer to the OrxonoxClass that is to be duplicated.
198    */
199    void PickupCollection::clone(OrxonoxClass*& item)
200    {
201        if(item == NULL)
202            item = new PickupCollection(this);
203
204        SUPER(PickupCollection, clone, item);
205
206        PickupCollection* pickup = orxonox_cast<PickupCollection*>(item);
207        // Clone all Pickupables this PickupCollection consist of.
208        for(std::list<CollectiblePickup*>::iterator it = this->pickups_.begin(); it != this->pickups_.end(); ++it)
209        {
210            Pickupable* newPickup = (*it)->clone();
211            CollectiblePickup* collectible = static_cast<CollectiblePickup*>(newPickup);
212            pickup->addPickupable(collectible);
213        }
214    }
215
216    /**
217    @brief
218        Get whether a given class, represented by the input Identifier, is a target of this PickupCollection.
219    @param carrier
220        A pointer to the PickupCarrier we want to know of, whether it is a target of this PickupCollection.
221    @return
222        Returns true if the PickupCarrier identified by the input PickupIdentififer it is a target of this PickupCollection, false if not.
223    */
224    bool PickupCollection::isTarget(const PickupCarrier* carrier) const
225    {
226        for(std::list<CollectiblePickup*>::const_iterator it = this->pickups_.begin(); it != this->pickups_.end(); ++it)
227        {
228            if(!carrier->isTarget(*it))
229                return false;
230        }
231
232        return true;
233    }
234
235    /**
236    @brief
237        Get the PickupIdentifier of this PickupCollection.
238        This is in fact the PickupCollectionIdentifier.
239    @return
240        Returns a pointer to the PickupIdentifier of this PickupCollection.
241    */
242    const PickupIdentifier* PickupCollection::getPickupIdentifier(void) const
243    {
244        return this->pickupCollectionIdentifier_;
245    }
246
247    /**
248    @brief
249        Add the input Pickupable to list of Pickupables combined by this PickupCollection.
250    @param pickup
251        The Pickupable to be added.
252    @return
253        Returns true if successful,
254    */
255    bool PickupCollection::addPickupable(CollectiblePickup* pickup)
256    {
257        if(pickup == NULL)
258            return false;
259
260        this->pickups_.push_back(pickup);
261        pickup->wasAddedToCollection(this);
262        return true;
263    }
264
265    /**
266    @brief
267        Get the Pickupable at the given index.
268    @param index
269        The index the Pickupable is fetched from.
270    @return
271        Returns a pointer to the Pickupable at the index given by index.
272    */
273    const Pickupable* PickupCollection::getPickupable(unsigned int index) const
274    {
275        unsigned int count = 0;
276        for (std::list<CollectiblePickup*>::const_iterator it = this->pickups_.begin(); it != this->pickups_.end(); ++it)
277        {
278            if (count == index)
279                return *it;
280            else
281                ++count;
282        }
283        return NULL;
284    }
285
286    /**
287    @brief
288        Removes the Pickup from the Collection.
289    @param pickup
290        The Pickup to be removed.
291    @return
292        Returns true if the pickup was in the collection.
293    */
294    bool PickupCollection::removePickupable(CollectiblePickup* pickup)
295    {
296        for(std::list<CollectiblePickup*>::iterator it = this->pickups_.begin(); it != this->pickups_.end(); ++it)
297        {
298            if (*it == pickup)
299            {
300                this->pickups_.erase(it);
301                pickup->wasRemovedFromCollection();
302                return true;
303            }
304        }
305        return false;
306    }
307
308    /**
309    @brief
310        Informs the PickupCollection, that one of its pickups has changed its used status to the input value.
311        This is used internally by the CollectiblePickup class.
312    @param changed
313        The value the used status has changed to.
314    */
315    void PickupCollection::pickupChangedUsed(bool changed)
316    {
317        if(changed)
318            this->usedCounter_++;
319        else
320            this->usedCounter_--;
321
322        this->changedUsedAction();
323    }
324
325    /**
326    @brief
327        Informs the PickupCollection, that one of its pickups has changed its picked up status to the input value.
328        This is used internally by the CollectiblePickup class.
329    @param changed
330        The value the picked up status has changed to.
331    */
332    void PickupCollection::pickupChangedPickedUp(bool changed)
333    {
334        if(changed)
335            this->pickedUpCounter_++;
336        else
337            this->pickedUpCounter_--;
338
339        this->changedPickedUpAction();
340    }
341
342    /**
343    @brief
344        Informs the PickupCollection, that one of its pickups has been disabled.
345        This is used internally by the CollectiblePickup class.
346    */
347    void PickupCollection::pickupDisabled(void)
348    {
349        this->disabledCounter_++;
350    }
351
352    /**
353    @brief
354        Facilitates the creation of a PickupSpawner upon dropping of the Pickupable.
355        This method must be implemented by any class directly inheriting from Pickupable. It is most easily done by just creating a new DroppedPickup, e.g.:
356        DroppedPickup(BaseObject* creator, Pickupable* pickup, const Vector3& position);
357    @return
358        Returns true if a spawner was created, false if not.
359    */
360    bool PickupCollection::createSpawner(void)
361    {
362        new DroppedPickup(this, this, this->getCarrier());
363        return true;
364    }
365
366}
Note: See TracBrowser for help on using the repository browser.