Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/pickup3/src/modules/pickup/PickupSpawner.cc @ 6475

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

Additional documentation, code niceifying and potential bug fixing. Also: Renamed DroppedItem to DroppedPickup.

  • Property svn:eol-style set to native
File size: 10.5 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 *      Daniel 'Huty' Haggenmueller
24 *   Co-authors:
25 *      Damian 'Mozork' Frick
26 *
27 */
28
29/**
30    @file
31    @brief Implementation of PickupSpawner.
32*/
33
34#include "PickupSpawner.h"
35
36#include "core/CoreIncludes.h"
37#include "core/Template.h"
38#include "core/XMLPort.h"
39#include "worldentities/pawns/Pawn.h"
40#include "PickupManager.h"
41#include "PickupRepresentation.h"
42
43namespace orxonox
44{
45
46    CreateFactory(PickupSpawner);
47
48    /**
49    @brief
50        Constructor. Creates a blank PickupSpawner.
51    @param creator
52        Pointer to the object which created this item.
53    */
54    PickupSpawner::PickupSpawner(BaseObject* creator) : StaticEntity(creator)
55    {
56        RegisterObject(PickupSpawner);
57       
58        this->initialize();
59    }
60
61    /**
62    @brief
63        Constructor, Creates a fully functional PickupSpawner.
64    @param creator
65        The creator of this PickupSpawner.
66    @param pickup
67        The Pickupable to be spawned by this PickupSpawner.
68    @param triggerDistance
69        The distance at which the PickupSpawner will trigger.
70    @param respawnTime
71        The minimum time between two spawns.
72    @param maySpawnedItems
73        The maximum number of items spawned by this PickupSpawner.
74    */
75    PickupSpawner::PickupSpawner(BaseObject* creator, Pickupable* pickup, float triggerDistance, float respawnTime, int maxSpawnedItems) : StaticEntity(creator)
76    {
77        RegisterObject(PickupSpawner);
78       
79        this->initialize();
80 
81        this->pickup_ = pickup;
82
83        this->triggerDistance_ = triggerDistance;
84        this->respawnTime_ = respawnTime;
85        this->setMaxSpawnedItems(maxSpawnedItems);
86       
87        if(this->pickup_ == NULL)
88        {
89            COUT(2) << "A PickupSpawner was created without a valid Pickupable. This won't work." << std::endl;
90            this->setActive(false);
91        }
92        else
93        {
94            PickupRepresentation* representation = PickupManager::getInstance().getRepresentation(this->pickup_->getPickupIdentifier());
95            this->attach(representation->getSpawnerRepresentation(this));
96        }
97    }
98
99    /**
100    @brief
101        Registers the object and sets some default values.
102    */
103    void PickupSpawner::initialize(void)
104    {
105        this->pickup_ = NULL;
106       
107        this->triggerDistance_ = 20;
108        this->respawnTime_ = 0;
109        this->maxSpawnedItems_ = INF;
110        this->spawnsRemaining_ = INF;
111    }
112
113    /**
114    @brief
115        Destructor.
116    */
117    PickupSpawner::~PickupSpawner()
118    {
119        if(this->pickup_ != NULL)
120            delete this->pickup_;
121    }
122
123    /**
124    @brief
125        Method for creating a PickupSpawner through XML.
126    @param xmlelement
127        XML element which contains the PickupSpawner.
128    @param mode
129        XMLPort mode.
130    */
131    void PickupSpawner::XMLPort(Element& xmlelement, XMLPort::Mode mode)
132    {
133        SUPER(PickupSpawner, XMLPort, xmlelement, mode);
134
135        XMLPortObject(PickupSpawner, Pickupable, "pickup", setPickupable, getPickupable, xmlelement, mode);
136       
137        XMLPortParam(PickupSpawner, "triggerDistance", setTriggerDistance, getTriggerDistance, xmlelement, mode);
138        XMLPortParam(PickupSpawner, "respawnTime", setRespawnTime, getRespawnTime, xmlelement, mode);
139        XMLPortParam(PickupSpawner, "maxSpawnedItems", setMaxSpawnedItems, getMaxSpawnedItems, xmlelement, mode);
140       
141        if(this->pickup_ == NULL)
142        {
143            COUT(2) << "A PickupSpawner was created without a valid Pickupable. This won't work." << std::endl;
144            this->setActive(false);
145        }
146        else
147        {
148            PickupRepresentation* representation = PickupManager::getInstance().getRepresentation(this->pickup_->getPickupIdentifier());
149            this->attach(representation->getSpawnerRepresentation(this));
150        }
151    }
152   
153    /**
154    @brief
155        Invoked when the activity has changed. Sets visibility of attached objects.
156    */
157    void PickupSpawner::changedActivity()
158    {
159        SUPER(PickupSpawner, changedActivity);
160
161        for (std::set<WorldEntity*>::const_iterator it = this->getAttachedObjects().begin(); it != this->getAttachedObjects().end(); it++)
162        {
163            (*it)->setVisible(this->isActive());
164        }
165    }
166     
167    /**
168    @brief
169        Tick, checks if any Pawn is close enough to trigger.
170    @param dt
171        Time since last tick.
172    */
173    //TODO: Replace this with a real DistanceTrigger? Or better with collisions?
174    void PickupSpawner::tick(float dt)
175    {
176        //! If the PickupSpawner is active.
177        if (this->isActive())
178        {
179            //! Iterate trough all Pawns.
180            for (ObjectList<Pawn>::iterator it = ObjectList<Pawn>::begin(); it != ObjectList<Pawn>::end(); ++it)
181            {
182                Vector3 distance = it->getWorldPosition() - this->getWorldPosition();
183                //! If a Pawn, that fits the target-range of the item spawned by this Pickup, is in trigger-distance.
184                if (distance.length() < this->triggerDistance_ && this->pickup_->isTarget(*it))
185                {
186                    this->trigger(*it);
187                }
188            }
189        }
190    }
191   
192    /**
193    @brief
194        Sets the maximum number of spawned items.
195    @param items
196        The maximum number of spawned items to be set.
197    */
198    void PickupSpawner::setMaxSpawnedItems(int items)
199    {
200        this->maxSpawnedItems_ = items;
201        this->spawnsRemaining_ = items;
202    }
203   
204    /**
205    @brief
206        Decrements the number of remaining spawns.
207        Sets the PickupSpawner to inactive for the duration of the respawnTime.
208        Destroys the PickupSpawner if the number of remaining spawns has reached zero.
209    */
210    void PickupSpawner::decrementSpawnsRemaining(void)
211    {
212        if(this->spawnsRemaining_ != INF)
213        {
214            this->spawnsRemaining_--;
215        }
216        if(this->spawnsRemaining_ != 0 && this->respawnTime_ > 0)
217        {
218            //TODO: Nicer? Does this even work?
219            this->respawnTimer_.setTimer(this->respawnTime_, false, createExecutor(createFunctor(&PickupSpawner::respawnTimerCallback, this)));
220
221            this->setActive(false);
222            this->fireEvent();
223        }
224        else
225        {
226            COUT(3) << "PickupSpawner empty, selfdestruct initialized." << std::endl;
227            this->setActive(false);
228            this->destroy();
229        }
230    }
231   
232    /**
233    @brief
234        Sets a Pickupable for the PickupSpawner to spawn.
235    @param pickup
236        The Pickupable to be set.
237    */
238    void PickupSpawner::setPickupable(Pickupable* pickup)
239    {
240        if(this->pickup_ != NULL)
241        {
242            COUT(1) << "In PickupSpawner: setPickupable called, with this->pickup_ already set." << std::endl;
243            return;
244        }
245        if(pickup == NULL)
246        {
247            COUT(1) << "In PickupSpawner: Argument of setPickupable is NULL." << std::endl;
248            return;
249        }
250       
251        this->pickup_ = pickup;
252    }
253   
254    /**
255    @brief
256        Get the Pickupable that is spawned by this PickupSpawner.
257    @return
258        Returns the Pickupable that is spawned by this PickupSpawner.
259    */
260    const Pickupable* PickupSpawner::getPickupable(void)
261    {
262        return this->pickup_;
263    }
264
265    /**
266    @brief
267        Trigger the PickupSpawner.
268        Adds the pickup to the Pawn that triggered, sets the timer to re-activate and deactives the PickupSpawner.
269    @param pawn
270        Pawn which triggered the PickupSpawner.
271    */
272    //TODO: Make more generic -> without pawn.
273    void PickupSpawner::trigger(Pawn* pawn)
274    {
275        if (this->isActive()) //!< Checks whether PickupItem is active.
276        {
277            PickupCarrier* carrier = dynamic_cast<PickupCarrier*>(pawn);
278            if(carrier == NULL)
279            {
280                COUT(1) << "This is bad. Pawn isn't PickupCarrier." << std::endl;
281                return;
282            }
283           
284            if(!carrier->isTarget(this->pickup_))
285            {
286                COUT(4) << "PickupSpawner triggered but Pawn wasn't a target of the Pickupable." << std::endl;
287                return;
288            }
289           
290            PickupCarrier* target = carrier->getTarget(this->pickup_);
291            Pickupable* pickup = this->getPickup();
292           
293            if(target != NULL || pickup != NULL)
294            {
295                if(carrier->pickup(pickup))
296                {
297                    this->decrementSpawnsRemaining();
298                }
299                else
300                {
301                    pickup->destroy();
302                }
303            }
304            else
305            {
306                //TODO: Really that severe?
307                if(target == NULL)
308                    COUT(1) << "PickupSpawner: Pickupable has no target." << std::endl;
309               
310                if(pickup == NULL)
311                {
312                    COUT(1) << "PickupSpawner: getPickup produced an error, no Pickupable created." << std::endl;
313                }
314                else
315                {
316                    pickup->destroy();
317                }
318            }
319        }
320    }
321
322    /**
323    @brief
324        Creates a new Pickupable.
325    @return
326        The Pickupable created.
327    */   
328    Pickupable* PickupSpawner::getPickup(void)
329    {
330        if(this->spawnsRemaining_ == 0)
331        {
332            COUT(1) << "Massive Error: PickupSpawner still alive until having spawned last item." << std::endl;
333            return NULL;
334        }
335       
336        Pickupable* pickup = this->pickup_->clone();
337        return pickup;
338    }
339
340    /**
341    @brief
342        Invoked by the timer, re-activates the PickupSpawner.
343    */
344    void PickupSpawner::respawnTimerCallback()
345    {
346        COUT(3) << "PickupSpawner reactivated." << std::endl;
347
348        this->setActive(true);
349    }
350}
Note: See TracBrowser for help on using the repository browser.