Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

Fixing small bug in Script (regarding number of executions).
Fixed bug in WorldEntity, that caused the visibility and activity to be synchronized incorrectly (since bVisibleMem and bActiveMem are not synchronized).
Some small changed in documentation.
Started "synchronizing" pickups. Seems to work (except GUI), but haven't done any extensive testing yet.

  • Property svn:eol-style set to native
File size: 10.3 KB
RevLine 
[2917]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:
[6405]25 *      Damian 'Mozork' Frick
[2917]26 *
27 */
28
29/**
[6540]30    @file PickupSpawner.cc
31    @brief Implementation of the PickupSpawner class.
[2917]32*/
33
34#include "PickupSpawner.h"
[3196]35
[2917]36#include "core/CoreIncludes.h"
[7493]37#include "core/GameMode.h"
[3196]38#include "core/Template.h"
[2917]39#include "core/XMLPort.h"
[5735]40#include "worldentities/pawns/Pawn.h"
[6466]41#include "PickupManager.h"
42#include "PickupRepresentation.h"
[2917]43
44namespace orxonox
45{
[5953]46
[2917]47    CreateFactory(PickupSpawner);
48
49    /**
[5947]50    @brief
[6421]51        Constructor. Creates a blank PickupSpawner.
[5947]52    @param creator
53        Pointer to the object which created this item.
[2917]54    */
[6540]55    PickupSpawner::PickupSpawner(BaseObject* creator) : StaticEntity(creator), pickup_(NULL)
[2917]56    {
[6540]57        RegisterObject(PickupSpawner);
[7163]58
[6514]59        this->initialize();
[5953]60    }
61
[6421]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.
[7401]73    @param maxSpawnedItems
[6421]74        The maximum number of items spawned by this PickupSpawner.
75    */
[6540]76    PickupSpawner::PickupSpawner(BaseObject* creator, Pickupable* pickup, float triggerDistance, float respawnTime, int maxSpawnedItems) : StaticEntity(creator), pickup_(NULL)
[5953]77    {
[6466]78        RegisterObject(PickupSpawner);
[7163]79
[5953]80        this->initialize();
[7163]81
[6405]82        this->pickup_ = pickup;
[5953]83
84        this->triggerDistance_ = triggerDistance;
85        this->respawnTime_ = respawnTime;
86        this->setMaxSpawnedItems(maxSpawnedItems);
[7163]87
[6475]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));
[7493]97            this->setActive(true); //TODO: Needed?
[6475]98        }
[5953]99    }
100
[6421]101    /**
102    @brief
103        Registers the object and sets some default values.
104    */
[5953]105    void PickupSpawner::initialize(void)
106    {
[6563]107        this->triggerDistance_ = 10;
[6405]108        this->respawnTime_ = 0;
[5953]109        this->maxSpawnedItems_ = INF;
110        this->spawnsRemaining_ = INF;
[7163]111        this->selfDestruct_ = false;
[2917]112    }
[5947]113
114    /**
115    @brief
116        Destructor.
117    */
[2917]118    PickupSpawner::~PickupSpawner()
119    {
[7163]120        if(this->selfDestruct_ && this->pickup_ != NULL)
[6478]121            this->pickup_->destroy();
[2917]122    }
[5947]123
[2917]124    /**
[5947]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.
[2917]131    */
132    void PickupSpawner::XMLPort(Element& xmlelement, XMLPort::Mode mode)
133    {
134        SUPER(PickupSpawner, XMLPort, xmlelement, mode);
135
[6421]136        XMLPortObject(PickupSpawner, Pickupable, "pickup", setPickupable, getPickupable, xmlelement, mode);
[7163]137
[2917]138        XMLPortParam(PickupSpawner, "triggerDistance", setTriggerDistance, getTriggerDistance, xmlelement, mode);
139        XMLPortParam(PickupSpawner, "respawnTime", setRespawnTime, getRespawnTime, xmlelement, mode);
[5953]140        XMLPortParam(PickupSpawner, "maxSpawnedItems", setMaxSpawnedItems, getMaxSpawnedItems, xmlelement, mode);
[7163]141
[6475]142        if(this->pickup_ == NULL)
[6405]143        {
[6475]144            COUT(2) << "A PickupSpawner was created without a valid Pickupable. This won't work." << std::endl;
145            this->setActive(false);
[6405]146        }
[6475]147        else
[6405]148        {
[6475]149            PickupRepresentation* representation = PickupManager::getInstance().getRepresentation(this->pickup_->getPickupIdentifier());
150            this->attach(representation->getSpawnerRepresentation(this));
[7493]151            this->setActive(true); //TODO: Needed?
[6405]152        }
[2917]153    }
[7163]154
[6421]155    /**
156    @brief
[6475]157        Invoked when the activity has changed. Sets visibility of attached objects.
[6421]158    */
[6475]159    void PickupSpawner::changedActivity()
[6405]160    {
[6475]161        SUPER(PickupSpawner, changedActivity);
[5947]162
[7493]163        if(GameMode::isMaster())
164            this->setVisible(this->isActive());
[5953]165    }
[7163]166
[2917]167    /**
[5947]168    @brief
169        Tick, checks if any Pawn is close enough to trigger.
170    @param dt
171        Time since last tick.
[2917]172    */
[7493]173    //TODO: Replace with collisions?
[2917]174    void PickupSpawner::tick(float dt)
175    {
[6540]176        SUPER(PickupSpawner, tick, dt);
[7163]177
[7493]178        // If the PickupSpawner is active.
179        if(GameMode::isMaster() && this->isActive())
[2917]180        {
[7163]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
[7493]183            // Iterate trough all Pawns.
[5929]184            for (ObjectList<Pawn>::iterator it = ObjectList<Pawn>::begin(); it != ObjectList<Pawn>::end(); ++it)
[2917]185            {
186                Vector3 distance = it->getWorldPosition() - this->getWorldPosition();
[6711]187                PickupCarrier* carrier = dynamic_cast<PickupCarrier*>(*it);
[7493]188                // If a Pawn, that fits the target-range of the item spawned by this Pickup, is in trigger-distance.
[6711]189                if (distance.length() < this->triggerDistance_ && carrier != NULL && carrier->isTarget(this->pickup_))
[6405]190                {
[2917]191                    this->trigger(*it);
[6405]192                }
[2917]193            }
194        }
195    }
[7163]196
[2917]197    /**
[5947]198    @brief
[6475]199        Sets the maximum number of spawned items.
200    @param items
201        The maximum number of spawned items to be set.
[2917]202    */
[6475]203    void PickupSpawner::setMaxSpawnedItems(int items)
[2917]204    {
[6475]205        this->maxSpawnedItems_ = items;
206        this->spawnsRemaining_ = items;
[6405]207    }
[7163]208
[6421]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    */
[6405]215    void PickupSpawner::decrementSpawnsRemaining(void)
216    {
217        if(this->spawnsRemaining_ != INF)
218            this->spawnsRemaining_--;
[7493]219
[6405]220        if(this->spawnsRemaining_ != 0 && this->respawnTime_ > 0)
221        {
[6512]222            this->startRespawnTimer();
[5953]223
[6405]224            this->setActive(false);
225            this->fireEvent();
226        }
227        else
[5953]228        {
[7163]229            COUT(4) << "PickupSpawner (&" << this << ") empty, selfdestruct initialized." << std::endl;
[5953]230            this->setActive(false);
[6475]231            this->destroy();
[5953]232        }
[2917]233    }
[7163]234
[6475]235    /**
236    @brief
[6512]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    }
[7163]243
[6512]244    /**
245    @brief
[6475]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        {
[7163]254            COUT(1) << "In PickupSpawner (&" << this << "): setPickupable called, with this->pickup_ already set." << std::endl;
[6475]255            return;
256        }
257        if(pickup == NULL)
258        {
[7163]259            COUT(1) << "In PickupSpawner (&" << this << "): Argument of setPickupable is NULL." << std::endl;
[6475]260            return;
261        }
[7163]262
[6475]263        this->pickup_ = pickup;
264    }
[7163]265
[6475]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    }
[5947]276
[2917]277    /**
[5947]278    @brief
[6475]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    {
[7493]286        if(this->isActive()) // Checks whether PickupSpawner is active.
[6475]287        {
[7163]288            COUT(4) << "PickupSpawner (&" << this << ") triggered and active." << std::endl;
289
[6475]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            }
[7163]296
[6475]297            if(!carrier->isTarget(this->pickup_))
298            {
[7163]299                COUT(4) << "PickupSpawner (&" << this << ") triggered but Pawn wasn't a target of the Pickupable." << std::endl;
[6475]300                return;
301            }
[7163]302
[6475]303            PickupCarrier* target = carrier->getTarget(this->pickup_);
304            Pickupable* pickup = this->getPickup();
[7163]305
[7493]306            assert(pickup);
307            assert(target);
308            assert(pickup->pickup(target));
[7163]309
[7493]310            this->decrementSpawnsRemaining();
[6475]311        }
312    }
313
314    /**
315    @brief
[6405]316        Creates a new Pickupable.
[5953]317    @return
[6405]318        The Pickupable created.
[7163]319    */
[6405]320    Pickupable* PickupSpawner::getPickup(void)
[5953]321    {
[6405]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        }
[7163]327
[6405]328        Pickupable* pickup = this->pickup_->clone();
329        return pickup;
[5953]330    }
331
332    /**
333    @brief
[5947]334        Invoked by the timer, re-activates the PickupSpawner.
[2917]335    */
336    void PickupSpawner::respawnTimerCallback()
337    {
[7163]338        COUT(4) << "PickupSpawner (&" << this << ") reactivated." << std::endl;
[2917]339
340        this->setActive(true);
341    }
342}
Note: See TracBrowser for help on using the repository browser.