Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 6540 was 6514, checked in by rgrieder, 15 years ago

Fixed intialisation bug in PickupSpawner.

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