Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

Merged presentation3 branch into trunk.

  • Property svn:eol-style set to native
File size: 10.9 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        this->selfDestruct_ = false;
110    }
111
112    /**
113    @brief
114        Destructor.
115    */
116    PickupSpawner::~PickupSpawner()
117    {
118        if(this->selfDestruct_ && this->pickup_ != NULL)
119            this->pickup_->destroy();
120    }
121
122    /**
123    @brief
124        Method for creating a PickupSpawner through XML.
125    @param xmlelement
126        XML element which contains the PickupSpawner.
127    @param mode
128        XMLPort mode.
129    */
130    void PickupSpawner::XMLPort(Element& xmlelement, XMLPort::Mode mode)
131    {
132        SUPER(PickupSpawner, XMLPort, xmlelement, mode);
133
134        XMLPortObject(PickupSpawner, Pickupable, "pickup", setPickupable, getPickupable, xmlelement, mode);
135
136        XMLPortParam(PickupSpawner, "triggerDistance", setTriggerDistance, getTriggerDistance, xmlelement, mode);
137        XMLPortParam(PickupSpawner, "respawnTime", setRespawnTime, getRespawnTime, xmlelement, mode);
138        XMLPortParam(PickupSpawner, "maxSpawnedItems", setMaxSpawnedItems, getMaxSpawnedItems, xmlelement, mode);
139
140        if(this->pickup_ == NULL)
141        {
142            COUT(2) << "A PickupSpawner was created without a valid Pickupable. This won't work." << std::endl;
143            this->setActive(false);
144        }
145        else
146        {
147            PickupRepresentation* representation = PickupManager::getInstance().getRepresentation(this->pickup_->getPickupIdentifier());
148            representation->setVisible(this->isActive());
149            this->attach(representation->getSpawnerRepresentation(this));
150            this->setActive(true);
151        }
152    }
153
154    /**
155    @brief
156        Invoked when the activity has changed. Sets visibility of attached objects.
157    */
158    void PickupSpawner::changedActivity()
159    {
160        SUPER(PickupSpawner, changedActivity);
161
162        this->setVisible(this->isActive());
163    }
164
165    /**
166    @brief
167        Tick, checks if any Pawn is close enough to trigger.
168    @param dt
169        Time since last tick.
170    */
171    //TODO: Replace with collisions.
172    void PickupSpawner::tick(float dt)
173    {
174        SUPER(PickupSpawner, tick, dt);
175
176        //! If the PickupSpawner is active.
177        if (this->isActive())
178        {
179            SmartPtr<PickupSpawner> temp = this; //Create a smart pointer to keep the PickupSpawner alive until we iterated through all Pawns (in case a Pawn takes the last pickup)
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                PickupCarrier* carrier = dynamic_cast<PickupCarrier*>(*it);
186                //! If a Pawn, that fits the target-range of the item spawned by this Pickup, is in trigger-distance.
187                if (distance.length() < this->triggerDistance_ && carrier != NULL && carrier->isTarget(this->pickup_))
188                {
189                    this->trigger(*it);
190                }
191            }
192        }
193    }
194
195    /**
196    @brief
197        Sets the maximum number of spawned items.
198    @param items
199        The maximum number of spawned items to be set.
200    */
201    void PickupSpawner::setMaxSpawnedItems(int items)
202    {
203        this->maxSpawnedItems_ = items;
204        this->spawnsRemaining_ = items;
205    }
206
207    /**
208    @brief
209        Decrements the number of remaining spawns.
210        Sets the PickupSpawner to inactive for the duration of the respawnTime.
211        Destroys the PickupSpawner if the number of remaining spawns has reached zero.
212    */
213    void PickupSpawner::decrementSpawnsRemaining(void)
214    {
215        if(this->spawnsRemaining_ != INF)
216        {
217            this->spawnsRemaining_--;
218        }
219        if(this->spawnsRemaining_ != 0 && this->respawnTime_ > 0)
220        {
221            this->startRespawnTimer();
222
223            this->setActive(false);
224            this->fireEvent();
225        }
226        else
227        {
228            COUT(4) << "PickupSpawner (&" << this << ") empty, selfdestruct initialized." << std::endl;
229            this->setActive(false);
230            this->destroy();
231        }
232    }
233
234    /**
235    @brief
236        Starts the respawn timer.
237    */
238    void PickupSpawner::startRespawnTimer(void)
239    {
240        this->respawnTimer_.setTimer(this->respawnTime_, false, createExecutor(createFunctor(&PickupSpawner::respawnTimerCallback, this)));
241    }
242
243    /**
244    @brief
245        Sets a Pickupable for the PickupSpawner to spawn.
246    @param pickup
247        The Pickupable to be set.
248    */
249    void PickupSpawner::setPickupable(Pickupable* pickup)
250    {
251        if(this->pickup_ != NULL)
252        {
253            COUT(1) << "In PickupSpawner (&" << this << "): setPickupable called, with this->pickup_ already set." << std::endl;
254            return;
255        }
256        if(pickup == NULL)
257        {
258            COUT(1) << "In PickupSpawner (&" << this << "): Argument of setPickupable is NULL." << std::endl;
259            return;
260        }
261
262        this->pickup_ = pickup;
263    }
264
265    /**
266    @brief
267        Get the Pickupable that is spawned by this PickupSpawner.
268    @return
269        Returns the Pickupable that is spawned by this PickupSpawner.
270    */
271    const Pickupable* PickupSpawner::getPickupable(void)
272    {
273        return this->pickup_;
274    }
275
276    /**
277    @brief
278        Trigger the PickupSpawner.
279        Adds the pickup to the Pawn that triggered, sets the timer to re-activate and deactives the PickupSpawner.
280    @param pawn
281        Pawn which triggered the PickupSpawner.
282    */
283    void PickupSpawner::trigger(Pawn* pawn)
284    {
285        if (this->isActive()) //!< Checks whether PickupSpawner is active.
286        {
287            COUT(4) << "PickupSpawner (&" << this << ") triggered and active." << std::endl;
288
289            PickupCarrier* carrier = dynamic_cast<PickupCarrier*>(pawn);
290            if(carrier == NULL)
291            {
292                COUT(1) << "This is bad. Pawn isn't PickupCarrier." << std::endl;
293                return;
294            }
295
296            if(!carrier->isTarget(this->pickup_))
297            {
298                COUT(4) << "PickupSpawner (&" << this << ") triggered but Pawn wasn't a target of the Pickupable." << std::endl;
299                return;
300            }
301
302            PickupCarrier* target = carrier->getTarget(this->pickup_);
303            Pickupable* pickup = this->getPickup();
304
305            if(target != NULL && pickup != NULL)
306            {
307                if(pickup->pickup(target))
308                    this->decrementSpawnsRemaining();
309                else
310                {
311                    this->selfDestruct_ = true;
312                    pickup->destroy();
313                }
314            }
315            else
316            {
317                if(target == NULL)
318                    COUT(1) << "PickupSpawner (&" << this << "): Pickupable has no target." << std::endl;
319
320                if(pickup == NULL)
321                    COUT(1) << "PickupSpawner (&" << this << "): getPickup produced an error, no Pickupable created." << std::endl;
322                else
323                {
324                    this->selfDestruct_ = true;
325                    pickup->destroy();
326                }
327            }
328        }
329    }
330
331    /**
332    @brief
333        Creates a new Pickupable.
334    @return
335        The Pickupable created.
336    */
337    Pickupable* PickupSpawner::getPickup(void)
338    {
339        if(this->spawnsRemaining_ == 0)
340        {
341            COUT(1) << "Massive Error: PickupSpawner still alive until having spawned last item." << std::endl;
342            return NULL;
343        }
344
345        Pickupable* pickup = this->pickup_->clone();
346        return pickup;
347    }
348
349    /**
350    @brief
351        Invoked by the timer, re-activates the PickupSpawner.
352    */
353    void PickupSpawner::respawnTimerCallback()
354    {
355        COUT(4) << "PickupSpawner (&" << this << ") reactivated." << std::endl;
356
357        this->setActive(true);
358    }
359}
Note: See TracBrowser for help on using the repository browser.