Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

Some small changes regarding output.

  • 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            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->respawnTimer_.setTimer(this->respawnTime_, false, createExecutor(createFunctor(&PickupSpawner::respawnTimerCallback, this)));
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        Sets a Pickupable for the PickupSpawner to spawn.
234    @param pickup
235        The Pickupable to be set.
236    */
237    void PickupSpawner::setPickupable(Pickupable* pickup)
238    {
239        if(this->pickup_ != NULL)
240        {
241            COUT(1) << "In PickupSpawner: setPickupable called, with this->pickup_ already set." << std::endl;
242            return;
243        }
244        if(pickup == NULL)
245        {
246            COUT(1) << "In PickupSpawner: Argument of setPickupable is NULL." << std::endl;
247            return;
248        }
249       
250        this->pickup_ = pickup;
251    }
252   
253    /**
254    @brief
255        Get the Pickupable that is spawned by this PickupSpawner.
256    @return
257        Returns the Pickupable that is spawned by this PickupSpawner.
258    */
259    const Pickupable* PickupSpawner::getPickupable(void)
260    {
261        return this->pickup_;
262    }
263
264    /**
265    @brief
266        Trigger the PickupSpawner.
267        Adds the pickup to the Pawn that triggered, sets the timer to re-activate and deactives the PickupSpawner.
268    @param pawn
269        Pawn which triggered the PickupSpawner.
270    */
271    //TODO: Make more generic -> without pawn.
272    void PickupSpawner::trigger(Pawn* pawn)
273    {
274        if (this->isActive()) //!< Checks whether PickupSpawner is active.
275        {
276            COUT(3) << "PickupSpawner triggered and active." << std::endl;
277           
278            PickupCarrier* carrier = dynamic_cast<PickupCarrier*>(pawn);
279            if(carrier == NULL)
280            {
281                COUT(1) << "This is bad. Pawn isn't PickupCarrier." << std::endl;
282                return;
283            }
284           
285            if(!carrier->isTarget(this->pickup_))
286            {
287                COUT(4) << "PickupSpawner triggered but Pawn wasn't a target of the Pickupable." << std::endl;
288                return;
289            }
290           
291            PickupCarrier* target = carrier->getTarget(this->pickup_);
292            Pickupable* pickup = this->getPickup();
293           
294            if(target != NULL && pickup != NULL)
295            {
296                if(target->pickup(pickup))
297                {
298                    this->decrementSpawnsRemaining();
299                }
300                else
301                {
302                    pickup->destroy();
303                }
304            }
305            else
306            {
307                //TODO: Really that severe?
308                if(target == NULL)
309                    COUT(1) << "PickupSpawner: Pickupable has no target." << std::endl;
310               
311                if(pickup == NULL)
312                {
313                    COUT(1) << "PickupSpawner: getPickup produced an error, no Pickupable created." << std::endl;
314                }
315                else
316                {
317                    pickup->destroy();
318                }
319            }
320        }
321    }
322
323    /**
324    @brief
325        Creates a new Pickupable.
326    @return
327        The Pickupable created.
328    */   
329    Pickupable* PickupSpawner::getPickup(void)
330    {
331        if(this->spawnsRemaining_ == 0)
332        {
333            COUT(1) << "Massive Error: PickupSpawner still alive until having spawned last item." << std::endl;
334            return NULL;
335        }
336       
337        Pickupable* pickup = this->pickup_->clone();
338        return pickup;
339    }
340
341    /**
342    @brief
343        Invoked by the timer, re-activates the PickupSpawner.
344    */
345    void PickupSpawner::respawnTimerCallback()
346    {
347        COUT(3) << "PickupSpawner reactivated." << std::endl;
348
349        this->setActive(true);
350    }
351}
Note: See TracBrowser for help on using the repository browser.