Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/modules/pickup/PickupSpawner.cc @ 6886

Last change on this file since 6886 was 6711, checked in by dafrick, 15 years ago

Merged pickup4 branch back to trunk.

  • 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 PickupSpawner.cc
31    @brief Implementation of the PickupSpawner class.
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), pickup_(NULL)
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), pickup_(NULL)
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->triggerDistance_ = 10;
106        this->respawnTime_ = 0;
107        this->maxSpawnedItems_ = INF;
108        this->spawnsRemaining_ = INF;
109    }
110
111    /**
112    @brief
113        Destructor.
114    */
115    PickupSpawner::~PickupSpawner()
116    {
117        if(this->pickup_ != NULL)
118            this->pickup_->destroy();
119    }
120
121    /**
122    @brief
123        Method for creating a PickupSpawner through XML.
124    @param xmlelement
125        XML element which contains the PickupSpawner.
126    @param mode
127        XMLPort mode.
128    */
129    void PickupSpawner::XMLPort(Element& xmlelement, XMLPort::Mode mode)
130    {
131        SUPER(PickupSpawner, XMLPort, xmlelement, mode);
132
133        XMLPortObject(PickupSpawner, Pickupable, "pickup", setPickupable, getPickupable, xmlelement, mode);
134       
135        XMLPortParam(PickupSpawner, "triggerDistance", setTriggerDistance, getTriggerDistance, xmlelement, mode);
136        XMLPortParam(PickupSpawner, "respawnTime", setRespawnTime, getRespawnTime, xmlelement, mode);
137        XMLPortParam(PickupSpawner, "maxSpawnedItems", setMaxSpawnedItems, getMaxSpawnedItems, xmlelement, mode);
138       
139        if(this->pickup_ == NULL)
140        {
141            COUT(2) << "A PickupSpawner was created without a valid Pickupable. This won't work." << std::endl;
142            this->setActive(false);
143        }
144        else
145        {
146            PickupRepresentation* representation = PickupManager::getInstance().getRepresentation(this->pickup_->getPickupIdentifier());
147            representation->setVisible(this->isActive());
148            this->attach(representation->getSpawnerRepresentation(this));
149            this->setActive(true);
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        this->setVisible(this->isActive());
162    }
163     
164    /**
165    @brief
166        Tick, checks if any Pawn is close enough to trigger.
167    @param dt
168        Time since last tick.
169    */
170    //TODO: Replace with collisions.
171    void PickupSpawner::tick(float dt)
172    {
173        SUPER(PickupSpawner, tick, 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                PickupCarrier* carrier = dynamic_cast<PickupCarrier*>(*it);
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_ && carrier != NULL && carrier->isTarget(this->pickup_))
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            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    void PickupSpawner::trigger(Pawn* pawn)
281    {
282        if (this->isActive()) //!< Checks whether PickupSpawner is active.
283        {
284            COUT(3) << "PickupSpawner triggered and active." << std::endl;
285           
286            PickupCarrier* carrier = dynamic_cast<PickupCarrier*>(pawn);
287            if(carrier == NULL)
288            {
289                COUT(1) << "This is bad. Pawn isn't PickupCarrier." << std::endl;
290                return;
291            }
292           
293            if(!carrier->isTarget(this->pickup_))
294            {
295                COUT(4) << "PickupSpawner triggered but Pawn wasn't a target of the Pickupable." << std::endl;
296                return;
297            }
298           
299            PickupCarrier* target = carrier->getTarget(this->pickup_);
300            Pickupable* pickup = this->getPickup();
301           
302            if(target != NULL && pickup != NULL)
303            {
304                if(target->pickup(pickup))
305                {
306                    this->decrementSpawnsRemaining();
307                }
308                else
309                {
310                    pickup->destroy();
311                }
312            }
313            else
314            {
315                if(target == NULL)
316                    COUT(1) << "PickupSpawner: Pickupable has no target." << std::endl;
317               
318                if(pickup == NULL)
319                {
320                    COUT(1) << "PickupSpawner: getPickup produced an error, no Pickupable created." << std::endl;
321                }
322                else
323                {
324                    pickup->destroy();
325                }
326            }
327        }
328    }
329
330    /**
331    @brief
332        Creates a new Pickupable.
333    @return
334        The Pickupable created.
335    */   
336    Pickupable* PickupSpawner::getPickup(void)
337    {
338        if(this->spawnsRemaining_ == 0)
339        {
340            COUT(1) << "Massive Error: PickupSpawner still alive until having spawned last item." << std::endl;
341            return NULL;
342        }
343       
344        Pickupable* pickup = this->pickup_->clone();
345        return pickup;
346    }
347
348    /**
349    @brief
350        Invoked by the timer, re-activates the PickupSpawner.
351    */
352    void PickupSpawner::respawnTimerCallback()
353    {
354        COUT(3) << "PickupSpawner reactivated." << std::endl;
355
356        this->setActive(true);
357    }
358}
Note: See TracBrowser for help on using the repository browser.