Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

Resolving some TODO's.

  • Property svn:eol-style set to native
File size: 10.4 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/GameMode.h"
38#include "core/Template.h"
39#include "core/XMLPort.h"
40
41#include "worldentities/pawns/Pawn.h"
42
43#include "PickupManager.h"
44#include "PickupRepresentation.h"
45
46namespace orxonox
47{
48
49    CreateFactory(PickupSpawner);
50
51    /**
52    @brief
53        Constructor. Creates a blank PickupSpawner.
54    @param creator
55        Pointer to the object which created this item.
56    */
57    PickupSpawner::PickupSpawner(BaseObject* creator) : StaticEntity(creator), pickup_(NULL)
58    {
59        RegisterObject(PickupSpawner);
60
61        this->initialize();
62    }
63
64    /**
65    @brief
66        Constructor, Creates a fully functional PickupSpawner.
67    @param creator
68        The creator of this PickupSpawner.
69    @param pickup
70        The Pickupable to be spawned by this PickupSpawner.
71    @param triggerDistance
72        The distance at which the PickupSpawner will trigger.
73    @param respawnTime
74        The minimum time between two spawns.
75    @param maxSpawnedItems
76        The maximum number of items spawned by this PickupSpawner.
77    */
78    PickupSpawner::PickupSpawner(BaseObject* creator, Pickupable* pickup, float triggerDistance, float respawnTime, int maxSpawnedItems) : StaticEntity(creator), pickup_(NULL)
79    {
80        RegisterObject(PickupSpawner);
81
82        this->initialize();
83
84        this->pickup_ = pickup;
85
86        this->triggerDistance_ = triggerDistance;
87        this->respawnTime_ = respawnTime;
88        this->setMaxSpawnedItems(maxSpawnedItems);
89
90        if(this->pickup_ == NULL)
91        {
92            COUT(2) << "A PickupSpawner was created without a valid Pickupable. This won't work." << std::endl;
93            this->setActive(false);
94        }
95        else
96        {
97            PickupRepresentation* representation = PickupManager::getInstance().getRepresentation(this->pickup_->getPickupIdentifier());
98            this->attach(representation->getSpawnerRepresentation(this));
99            this->setActive(true);
100        }
101    }
102
103    /**
104    @brief
105        Registers the object and sets some default values.
106    */
107    void PickupSpawner::initialize(void)
108    {
109        this->triggerDistance_ = 10;
110        this->respawnTime_ = 0; //TODO: Smart? Shouldn't we have a better mechanism to prevent unwanted multiple pickups?
111        this->maxSpawnedItems_ = INF;
112        this->spawnsRemaining_ = INF;
113        this->selfDestruct_ = false;
114    }
115
116    /**
117    @brief
118        Destructor.
119    */
120    PickupSpawner::~PickupSpawner()
121    {
122        if(this->selfDestruct_ && this->pickup_ != NULL)
123            this->pickup_->destroy();
124    }
125
126    /**
127    @brief
128        Method for creating a PickupSpawner through XML.
129    @param xmlelement
130        XML element which contains the PickupSpawner.
131    @param mode
132        XMLPort mode.
133    */
134    void PickupSpawner::XMLPort(Element& xmlelement, XMLPort::Mode mode)
135    {
136        SUPER(PickupSpawner, XMLPort, xmlelement, mode);
137
138        XMLPortObject(PickupSpawner, Pickupable, "pickup", setPickupable, getPickupable, xmlelement, mode);
139
140        XMLPortParam(PickupSpawner, "triggerDistance", setTriggerDistance, getTriggerDistance, xmlelement, mode);
141        XMLPortParam(PickupSpawner, "respawnTime", setRespawnTime, getRespawnTime, xmlelement, mode);
142        XMLPortParam(PickupSpawner, "maxSpawnedItems", setMaxSpawnedItems, getMaxSpawnedItems, xmlelement, mode);
143
144        if(this->pickup_ == NULL)
145        {
146            COUT(2) << "A PickupSpawner was created without a valid Pickupable. This won't work." << std::endl;
147            this->setActive(false);
148        }
149        else
150        {
151            PickupRepresentation* representation = PickupManager::getInstance().getRepresentation(this->pickup_->getPickupIdentifier());
152            this->attach(representation->getSpawnerRepresentation(this));
153            this->setActive(true); //TODO: Needed?
154        }
155    }
156
157    /**
158    @brief
159        Invoked when the activity has changed. Sets visibility of attached objects.
160    */
161    void PickupSpawner::changedActivity()
162    {
163        SUPER(PickupSpawner, changedActivity);
164
165        if(GameMode::isMaster())
166            this->setVisible(this->isActive());
167    }
168
169    /**
170    @brief
171        Tick, checks if any Pawn is close enough to trigger.
172    @param dt
173        Time since last tick.
174    */
175    //TODO: Replace with collisions?
176    void PickupSpawner::tick(float dt)
177    {
178        SUPER(PickupSpawner, tick, dt);
179
180        // If the PickupSpawner is active.
181        if(GameMode::isMaster() && this->isActive())
182        {
183            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)
184
185            // Iterate trough all Pawns.
186            for (ObjectList<Pawn>::iterator it = ObjectList<Pawn>::begin(); it != ObjectList<Pawn>::end(); ++it)
187            {
188                Vector3 distance = it->getWorldPosition() - this->getWorldPosition();
189                PickupCarrier* carrier = dynamic_cast<PickupCarrier*>(*it);
190                // If a Pawn, that fits the target-range of the item spawned by this Pickup, is in trigger-distance.
191                if (distance.length() < this->triggerDistance_ && carrier != NULL)
192                {
193                    if(carrier->isTarget(this->pickup_))
194                        this->trigger(*it);
195                }
196            }
197        }
198    }
199
200    /**
201    @brief
202        Sets the maximum number of spawned items.
203    @param items
204        The maximum number of spawned items to be set.
205    */
206    void PickupSpawner::setMaxSpawnedItems(int items)
207    {
208        this->maxSpawnedItems_ = items;
209        this->spawnsRemaining_ = items;
210    }
211
212    /**
213    @brief
214        Decrements the number of remaining spawns.
215        Sets the PickupSpawner to inactive for the duration of the respawnTime.
216        Destroys the PickupSpawner if the number of remaining spawns has reached zero.
217    */
218    void PickupSpawner::decrementSpawnsRemaining(void)
219    {
220        if(this->spawnsRemaining_ != INF)
221            this->spawnsRemaining_--;
222
223        if(this->spawnsRemaining_ != 0 && this->respawnTime_ > 0)
224        {
225            this->startRespawnTimer();
226
227            this->setActive(false);
228            this->fireEvent();
229        }
230        else
231        {
232            COUT(4) << "PickupSpawner (&" << this << ") empty, selfdestruct initialized." << std::endl;
233            this->setActive(false);
234            this->destroy();
235        }
236    }
237
238    /**
239    @brief
240        Starts the respawn timer.
241    */
242    void PickupSpawner::startRespawnTimer(void)
243    {
244        this->respawnTimer_.setTimer(this->respawnTime_, false, createExecutor(createFunctor(&PickupSpawner::respawnTimerCallback, this)));
245    }
246
247    /**
248    @brief
249        Sets a Pickupable for the PickupSpawner to spawn.
250    @param pickup
251        The Pickupable to be set.
252    */
253    void PickupSpawner::setPickupable(Pickupable* pickup)
254    {
255        if(this->pickup_ != NULL)
256        {
257            COUT(1) << "In PickupSpawner (&" << this << "): setPickupable called, with this->pickup_ already set." << std::endl;
258            return;
259        }
260        if(pickup == NULL)
261        {
262            COUT(1) << "In PickupSpawner (&" << this << "): Argument of setPickupable is NULL." << std::endl;
263            return;
264        }
265
266        this->pickup_ = pickup;
267    }
268
269    /**
270    @brief
271        Get the Pickupable that is spawned by this PickupSpawner.
272    @return
273        Returns the Pickupable that is spawned by this PickupSpawner.
274    */
275    const Pickupable* PickupSpawner::getPickupable(void) const
276    {
277        return this->pickup_;
278    }
279
280    /**
281    @brief
282        Trigger the PickupSpawner.
283        Adds the pickup to the Pawn that triggered, sets the timer to re-activate and deactives the PickupSpawner.
284    @param pawn
285        Pawn which triggered the PickupSpawner.
286    */
287    void PickupSpawner::trigger(Pawn* pawn)
288    {
289        if(this->isActive()) // Checks whether PickupSpawner is active.
290        {
291            COUT(4) << "PickupSpawner (&" << this << ") triggered and active." << std::endl;
292
293            PickupCarrier* carrier = dynamic_cast<PickupCarrier*>(pawn);
294            if(carrier == NULL)
295            {
296                COUT(1) << "This is bad. Pawn isn't PickupCarrier." << std::endl;
297                return;
298            }
299
300            if(!carrier->isTarget(this->pickup_))
301            {
302                COUT(4) << "PickupSpawner (&" << this << ") triggered but Pawn wasn't a target of the Pickupable." << std::endl;
303                return;
304            }
305
306            PickupCarrier* target = carrier->getTarget(this->pickup_);
307            Pickupable* pickup = this->getPickup();
308
309            assert(pickup);
310            assert(target);
311            assert(pickup->pickup(target));
312
313            this->decrementSpawnsRemaining();
314        }
315    }
316
317    /**
318    @brief
319        Creates a new Pickupable.
320    @return
321        The Pickupable created.
322    */
323    Pickupable* PickupSpawner::getPickup(void)
324    {
325        if(this->spawnsRemaining_ == 0)
326        {
327            COUT(1) << "Massive Error: PickupSpawner still alive until having spawned last item." << std::endl;
328            return NULL;
329        }
330
331        Pickupable* pickup = this->pickup_->clone();
332        return pickup;
333    }
334
335    /**
336    @brief
337        Invoked by the timer, re-activates the PickupSpawner.
338    */
339    void PickupSpawner::respawnTimerCallback()
340    {
341        COUT(4) << "PickupSpawner (&" << this << ") reactivated." << std::endl;
342
343        this->setActive(true);
344    }
345}
Note: See TracBrowser for help on using the repository browser.