Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

Cleanup and bug fixes.

  • Property svn:eol-style set to native
File size: 10.7 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            this->pickup_->destroy();
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            representation->setVisible(this->isActive());
150            this->attach(representation->getSpawnerRepresentation(this));
151            this->setActive(true);
152        }
153    }
154   
155    /**
156    @brief
157        Invoked when the activity has changed. Sets visibility of attached objects.
158    */
159    void PickupSpawner::changedActivity()
160    {
161        SUPER(PickupSpawner, changedActivity);
162
163        for (std::set<WorldEntity*>::const_iterator it = this->getAttachedObjects().begin(); it != this->getAttachedObjects().end(); it++)
164        {
165            (*it)->setVisible(this->isActive());
166        }
167    }
168     
169    /**
170    @brief
171        Tick, checks if any Pawn is close enough to trigger.
172    @param dt
173        Time since last tick.
174    */
175    //TODO: Replace this with a real DistanceTrigger? Or better with collisions?
176    void PickupSpawner::tick(float dt)
177    {
178        //! If the PickupSpawner is active.
179        if (this->isActive())
180        {
181            //! Iterate trough all Pawns.
182            for (ObjectList<Pawn>::iterator it = ObjectList<Pawn>::begin(); it != ObjectList<Pawn>::end(); ++it)
183            {
184                Vector3 distance = it->getWorldPosition() - this->getWorldPosition();
185                //! If a Pawn, that fits the target-range of the item spawned by this Pickup, is in trigger-distance.
186                if (distance.length() < this->triggerDistance_ && this->pickup_->isTarget(*it))
187                {
188                    this->trigger(*it);
189                }
190            }
191        }
192    }
193   
194    /**
195    @brief
196        Sets the maximum number of spawned items.
197    @param items
198        The maximum number of spawned items to be set.
199    */
200    void PickupSpawner::setMaxSpawnedItems(int items)
201    {
202        this->maxSpawnedItems_ = items;
203        this->spawnsRemaining_ = items;
204    }
205   
206    /**
207    @brief
208        Decrements the number of remaining spawns.
209        Sets the PickupSpawner to inactive for the duration of the respawnTime.
210        Destroys the PickupSpawner if the number of remaining spawns has reached zero.
211    */
212    void PickupSpawner::decrementSpawnsRemaining(void)
213    {
214        if(this->spawnsRemaining_ != INF)
215        {
216            this->spawnsRemaining_--;
217        }
218        if(this->spawnsRemaining_ != 0 && this->respawnTime_ > 0)
219        {
220            //TODO: Nicer? Does this even work?
221            this->respawnTimer_.setTimer(this->respawnTime_, false, createExecutor(createFunctor(&PickupSpawner::respawnTimerCallback, this)));
222
223            this->setActive(false);
224            this->fireEvent();
225        }
226        else
227        {
228            COUT(3) << "PickupSpawner empty, selfdestruct initialized." << std::endl;
229            this->setActive(false);
230            this->destroy();
231        }
232    }
233   
234    /**
235    @brief
236        Sets a Pickupable for the PickupSpawner to spawn.
237    @param pickup
238        The Pickupable to be set.
239    */
240    void PickupSpawner::setPickupable(Pickupable* pickup)
241    {
242        if(this->pickup_ != NULL)
243        {
244            COUT(1) << "In PickupSpawner: setPickupable called, with this->pickup_ already set." << std::endl;
245            return;
246        }
247        if(pickup == NULL)
248        {
249            COUT(1) << "In PickupSpawner: Argument of setPickupable is NULL." << std::endl;
250            return;
251        }
252       
253        this->pickup_ = pickup;
254    }
255   
256    /**
257    @brief
258        Get the Pickupable that is spawned by this PickupSpawner.
259    @return
260        Returns the Pickupable that is spawned by this PickupSpawner.
261    */
262    const Pickupable* PickupSpawner::getPickupable(void)
263    {
264        return this->pickup_;
265    }
266
267    /**
268    @brief
269        Trigger the PickupSpawner.
270        Adds the pickup to the Pawn that triggered, sets the timer to re-activate and deactives the PickupSpawner.
271    @param pawn
272        Pawn which triggered the PickupSpawner.
273    */
274    //TODO: Make more generic -> without pawn.
275    void PickupSpawner::trigger(Pawn* pawn)
276    {
277        COUT(1) << "PickupSpawner triggered." << std::endl;
278        if (this->isActive()) //!< Checks whether PickupSpawner is active.
279        {
280            COUT(1) << "PickupSpawner triggered and active." << std::endl;
281           
282            PickupCarrier* carrier = dynamic_cast<PickupCarrier*>(pawn);
283            if(carrier == NULL)
284            {
285                COUT(1) << "This is bad. Pawn isn't PickupCarrier." << std::endl;
286                return;
287            }
288           
289            if(!carrier->isTarget(this->pickup_))
290            {
291                COUT(4) << "PickupSpawner triggered but Pawn wasn't a target of the Pickupable." << std::endl;
292                return;
293            }
294           
295            PickupCarrier* target = carrier->getTarget(this->pickup_);
296            Pickupable* pickup = this->getPickup();
297           
298            if(target != NULL || pickup != NULL)
299            {
300                if(carrier->pickup(pickup))
301                {
302                    this->decrementSpawnsRemaining();
303                }
304                else
305                {
306                    pickup->destroy();
307                }
308            }
309            else
310            {
311                //TODO: Really that severe?
312                if(target == NULL)
313                    COUT(1) << "PickupSpawner: Pickupable has no target." << std::endl;
314               
315                if(pickup == NULL)
316                {
317                    COUT(1) << "PickupSpawner: getPickup produced an error, no Pickupable created." << std::endl;
318                }
319                else
320                {
321                    pickup->destroy();
322                }
323            }
324        }
325    }
326
327    /**
328    @brief
329        Creates a new Pickupable.
330    @return
331        The Pickupable created.
332    */   
333    Pickupable* PickupSpawner::getPickup(void)
334    {
335        if(this->spawnsRemaining_ == 0)
336        {
337            COUT(1) << "Massive Error: PickupSpawner still alive until having spawned last item." << std::endl;
338            return NULL;
339        }
340       
341        Pickupable* pickup = this->pickup_->clone();
342        return pickup;
343    }
344
345    /**
346    @brief
347        Invoked by the timer, re-activates the PickupSpawner.
348    */
349    void PickupSpawner::respawnTimerCallback()
350    {
351        COUT(3) << "PickupSpawner reactivated." << std::endl;
352
353        this->setActive(true);
354    }
355}
Note: See TracBrowser for help on using the repository browser.