Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 11484 was 11103, checked in by landauf, 9 years ago

fixed warnings (release build).
fixed error in GravityBombField

  • 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    RegisterClass(PickupSpawner);
50
51    /**
52    @brief
53        Constructor. Creates a blank PickupSpawner.
54    */
55    PickupSpawner::PickupSpawner(Context* context) : StaticEntity(context), pickup_(nullptr), representation_(nullptr), pickupTemplate_(nullptr)
56    {
57        RegisterObject(PickupSpawner);
58
59        this->initialize();
60    }
61
62    /**
63    @brief
64        Registers the object and sets some default values.
65    */
66    void PickupSpawner::initialize(void)
67    {
68        this->triggerDistance_ = 10;
69        this->respawnTime_ = 5.0f;
70        this->maxSpawnedItems_ = INF;
71        this->spawnsRemaining_ = INF;
72        this->selfDestruct_ = false;
73
74        this->setPickupable(nullptr);
75    }
76
77    /**
78    @brief
79        Destructor.
80    */
81    PickupSpawner::~PickupSpawner()
82    {
83        if(this->isInitialized() && this->selfDestruct_ && this->pickup_ != nullptr)
84            this->pickup_->destroy();
85    }
86
87    /**
88    @brief
89        Factory method, Creates a fully functional PickupSpawner.
90    @param context
91        The context of this PickupSpawner.
92    @param pickup
93        The Pickupable to be spawned by this PickupSpawner.
94    @param carrier
95        The PickupCarrier that carried the input pickup before it was dropped.
96    @param triggerDistance
97        The distance at which the PickupSpawner will trigger.
98    */
99    /*static*/ PickupSpawner* PickupSpawner::createDroppedPickup(Context* context, Pickupable* pickup, PickupCarrier* carrier, float triggerDistance)
100    {
101        PickupSpawner* spawner = new PickupSpawner(context);
102
103        spawner->setPickupable(pickup);
104        spawner->setTriggerDistance(triggerDistance);
105        spawner->setMaxSpawnedItems(1);
106
107        spawner->setPosition(carrier->getCarrierPosition());
108        spawner->block(carrier);
109
110        return spawner;
111    }
112
113    /**
114    @brief
115        Method for creating a PickupSpawner through XML.
116    @param xmlelement
117        XML element which contains the PickupSpawner.
118    @param mode
119        XMLPort mode.
120    */
121    void PickupSpawner::XMLPort(Element& xmlelement, XMLPort::Mode mode)
122    {
123        SUPER(PickupSpawner, XMLPort, xmlelement, mode);
124
125        XMLPortParam(PickupSpawner, "pickup", setPickupTemplateName, getPickupTemplateName, xmlelement, mode);
126        XMLPortParam(PickupSpawner, "triggerDistance", setTriggerDistance, getTriggerDistance, xmlelement, mode);
127        XMLPortParam(PickupSpawner, "respawnTime", setRespawnTime, getRespawnTime, xmlelement, mode);
128        XMLPortParam(PickupSpawner, "maxSpawnedItems", setMaxSpawnedItems, getMaxSpawnedItems, xmlelement, mode);
129    }
130
131    /**
132    @brief
133        Tick, checks if any Pawn is close enough to trigger.
134    @param dt
135        Time since last tick.
136    */
137    //TODO: Replace with collisions?
138    void PickupSpawner::tick(float dt)
139    {
140        SUPER(PickupSpawner, tick, dt);
141
142        // If the PickupSpawner is active.
143        if(GameMode::isMaster() && this->isActive())
144        {
145            // TODO: why is this a WeakPtr when the comment says StrongPtr?
146            WeakPtr<PickupSpawner> spawner = this; // Create a strong pointer to keep the PickupSpawner alive until we iterated through all Pawns (in case a Pawn takes the last pickup)
147
148            // Remove PickupCarriers from the blocked list if they have exceeded their time.
149            for(std::map<PickupCarrier*, std::time_t>::iterator it = this->blocked_.begin(); it != this->blocked_.end(); )
150            {
151                std::map<PickupCarrier*, std::time_t>::iterator temp = it;
152                it++;
153                if(temp->second < std::time(0))
154                    this->blocked_.erase(temp);
155            }
156
157            // Iterate trough all Pawns.
158            for(Pawn* pawn : ObjectList<Pawn>())
159            {
160                if(spawner == nullptr) // Stop if the PickupSpawner has been deleted (e.g. because it has run out of pickups to distribute).
161                    break;
162
163                Vector3 distance = pawn->getWorldPosition() - this->getWorldPosition();
164                PickupCarrier* carrier = static_cast<PickupCarrier*>(pawn);
165                // If a PickupCarrier, that fits the target-range of the Pickupable spawned by this PickupSpawner, is in trigger-distance and the carrier is not blocked.
166                if(distance.length() < this->triggerDistance_ && carrier != nullptr && this->blocked_.find(carrier) == this->blocked_.end())
167                {
168                    if(carrier->isTarget(this->pickup_))
169                        this->trigger(pawn);
170                }
171            }
172        }
173    }
174
175    /**
176    @brief
177        Trigger the PickupSpawner.
178        Adds the pickup to the Pawn that triggered, sets the timer to re-activate and deactives the PickupSpawner.
179    @param carrier
180        Carrier which triggered the PickupSpawner.
181    */
182    void PickupSpawner::trigger(PickupCarrier* carrier)
183    {
184        orxout(verbose, context::pickups) << "PickupSpawner (&" << this << ") triggered and active." << endl;
185
186        PickupCarrier* target = carrier->getTarget(this->pickup_);
187
188        this->block(carrier);
189
190        assert(target);
191        bool pickedUp = this->pickup_->pickup(target);
192        assert(pickedUp);
193        (void)pickedUp; // To avoid compiler warning.
194
195        this->setPickupable(nullptr);
196        this->decrementSpawnsRemaining();
197    }
198
199    void PickupSpawner::setPickupTemplateName(const std::string& name)
200    {
201        Template* temp = Template::getTemplate(name);
202        if (temp)
203            this->setPickupTemplate(temp);
204    }
205
206    void PickupSpawner::setPickupTemplate(Template* temp)
207    {
208        this->pickupTemplate_ = temp;
209        this->pickupTemplateName_ = temp->getName();
210
211        this->setPickupable(this->createPickup());
212    }
213
214    /**
215    @brief
216        Sets the maximum number of spawned items.
217    @param items
218        The maximum number of spawned items to be set.
219    */
220    void PickupSpawner::setMaxSpawnedItems(int items)
221    {
222        this->maxSpawnedItems_ = items;
223        this->spawnsRemaining_ = items;
224    }
225
226    /**
227    @brief
228        Decrements the number of remaining spawns.
229        Sets the PickupSpawner to inactive for the duration of the respawnTime.
230        Destroys the PickupSpawner if the number of remaining spawns has reached zero.
231    */
232    void PickupSpawner::decrementSpawnsRemaining(void)
233    {
234        if(this->spawnsRemaining_ != INF)
235            this->spawnsRemaining_--;
236
237        this->setActive(false);
238
239        if(this->spawnsRemaining_ != 0 && this->respawnTime_ > 0)
240        {
241            this->startRespawnTimer();
242            this->fireEvent();
243        }
244        else
245        {
246            orxout(verbose, context::pickups) << "PickupSpawner (&" << this << ") empty, selfdestruct initialized." << endl;
247            this->destroy();
248        }
249    }
250
251    /**
252    @brief
253        Starts the respawn timer.
254    */
255    void PickupSpawner::startRespawnTimer(void)
256    {
257        this->respawnTimer_.setTimer(this->respawnTime_, false, createExecutor(createFunctor(&PickupSpawner::respawnTimerCallback, this)));
258    }
259
260    /**
261    @brief
262        Invoked by the timer, re-activates the PickupSpawner.
263    */
264    void PickupSpawner::respawnTimerCallback()
265    {
266        orxout(verbose, context::pickups) << "PickupSpawner (&" << this << ") reactivated." << endl;
267
268        this->setPickupable(this->createPickup());
269    }
270
271    /**
272    @brief
273        Creates a new Pickupable.
274    @return
275        The Pickupable created.
276    */
277    Pickupable* PickupSpawner::createPickup(void)
278    {
279        if(this->spawnsRemaining_ == 0)
280        {
281            orxout(internal_error, context::pickups) << "Massive Error: PickupSpawner still alive until having spawned last item." << endl;
282            return nullptr;
283        }
284
285        if (this->pickupTemplate_ != nullptr)
286        {
287            Identifier* identifier = this->pickupTemplate_->getBaseclassIdentifier();
288            if (identifier != nullptr)
289            {
290                Pickupable* pickup = orxonox_cast<Pickupable*>(identifier->fabricate(this->getContext()));
291                orxonox_cast<BaseObject*>(pickup)->addTemplate(this->pickupTemplate_);
292                return pickup;
293            }
294            else
295                orxout(internal_error, context::pickups) << "No base class defined in pickup-template " << this->pickupTemplateName_ << endl;
296        }
297
298        return nullptr;
299    }
300
301    /**
302    @brief
303        Sets a Pickupable for the PickupSpawner to spawn.
304    @param pickup
305        The Pickupable to be set.
306    */
307    void PickupSpawner::setPickupable(Pickupable* pickup)
308    {
309        if (this->representation_ != nullptr)
310        {
311            this->representation_->destroy();
312            this->representation_ = nullptr;
313        }
314
315        if (pickup != nullptr)
316        {
317            if (this->pickup_ != nullptr)
318                this->pickup_->destroy();
319
320            PickupRepresentation* representation = PickupManager::getInstance().getRepresentation(pickup->getRepresentationName());
321            this->representation_ = representation->createSpawnerRepresentation(this);
322            this->attach(this->representation_);
323            this->setActive(true);
324        }
325        else
326        {
327            this->setActive(false);
328        }
329
330        this->pickup_ = pickup;
331    }
332}
Note: See TracBrowser for help on using the repository browser.