Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

Some more documenting.

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