Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

Small error in Pickup Spawner.

  • Property svn:eol-style set to native
File size: 10.6 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        COUT(1) << "PickupSpawner triggered." << std::endl;
275        if (this->isActive()) //!< Checks whether PickupSpawner is active.
276        {
277            COUT(1) << "PickupSpawner triggered and active." << std::endl;
278           
279            PickupCarrier* carrier = dynamic_cast<PickupCarrier*>(pawn);
280            if(carrier == NULL)
281            {
282                COUT(1) << "This is bad. Pawn isn't PickupCarrier." << std::endl;
283                return;
284            }
285           
286            if(!carrier->isTarget(this->pickup_))
287            {
288                COUT(4) << "PickupSpawner triggered but Pawn wasn't a target of the Pickupable." << std::endl;
289                return;
290            }
291           
292            PickupCarrier* target = carrier->getTarget(this->pickup_);
293            Pickupable* pickup = this->getPickup();
294           
295            if(target != NULL && pickup != NULL)
296            {
297                if(target->pickup(pickup))
298                {
299                    this->decrementSpawnsRemaining();
300                }
301                else
302                {
303                    pickup->destroy();
304                }
305            }
306            else
307            {
308                //TODO: Really that severe?
309                if(target == NULL)
310                    COUT(1) << "PickupSpawner: Pickupable has no target." << std::endl;
311               
312                if(pickup == NULL)
313                {
314                    COUT(1) << "PickupSpawner: getPickup produced an error, no Pickupable created." << std::endl;
315                }
316                else
317                {
318                    pickup->destroy();
319                }
320            }
321        }
322    }
323
324    /**
325    @brief
326        Creates a new Pickupable.
327    @return
328        The Pickupable created.
329    */   
330    Pickupable* PickupSpawner::getPickup(void)
331    {
332        if(this->spawnsRemaining_ == 0)
333        {
334            COUT(1) << "Massive Error: PickupSpawner still alive until having spawned last item." << std::endl;
335            return NULL;
336        }
337       
338        Pickupable* pickup = this->pickup_->clone();
339        return pickup;
340    }
341
342    /**
343    @brief
344        Invoked by the timer, re-activates the PickupSpawner.
345    */
346    void PickupSpawner::respawnTimerCallback()
347    {
348        COUT(3) << "PickupSpawner reactivated." << std::endl;
349
350        this->setActive(true);
351    }
352}
Note: See TracBrowser for help on using the repository browser.