Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/AsteroidMining_HS17/src/modules/pickup/PickupSpawner.cc @ 11823

Last change on this file since 11823 was 11609, checked in by remartin, 7 years ago

Solved pickup problem with tiny adaptation in Pawn.h and PickupSpawner.cc. Started work on SpicedAsteroidField.

  • 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 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                // Stop if the PickupSpawner has been deleted (e.g. because it has run out of pickups to distribute). 2nd condition prevents a possible error in isTarget(...) below.
161                if(spawner == nullptr || this->pickup_ == nullptr) 
162                    break;
163
164                if(!(pawn->doesAcceptPickups())){continue;} // skip those pawns, e.g. AsteroidMinables.
165
166                Vector3 distance = pawn->getWorldPosition() - this->getWorldPosition();
167                PickupCarrier* carrier = static_cast<PickupCarrier*>(pawn);
168                // 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.
169                if(distance.length() < this->triggerDistance_ && carrier != nullptr && this->blocked_.find(carrier) == this->blocked_.end())
170                {
171                    if(carrier->isTarget(this->pickup_))
172                        this->trigger(pawn);
173                }
174            }
175        }
176    }
177
178    /**
179    @brief
180        Trigger the PickupSpawner.
181        Adds the pickup to the Pawn that triggered, sets the timer to re-activate and deactives the PickupSpawner.
182    @param carrier
183        Carrier which triggered the PickupSpawner.
184    */
185    void PickupSpawner::trigger(PickupCarrier* carrier)
186    {
187        orxout(verbose, context::pickups) << "PickupSpawner (&" << this << ") triggered and active." << endl;
188
189        PickupCarrier* target = carrier->getTarget(this->pickup_);
190
191        this->block(carrier);
192
193        assert(target);
194        bool pickedUp = this->pickup_->pickup(target);
195        assert(pickedUp);
196        (void)pickedUp; // To avoid compiler warning.
197
198        this->setPickupable(nullptr);
199        this->decrementSpawnsRemaining();
200    }
201
202    void PickupSpawner::setPickupTemplateName(const std::string& name)
203    {
204        Template* temp = Template::getTemplate(name);
205        if (temp)
206            this->setPickupTemplate(temp);
207    }
208
209    void PickupSpawner::setPickupTemplate(Template* temp)
210    {
211        this->pickupTemplate_ = temp;
212        this->pickupTemplateName_ = temp->getName();
213
214        this->setPickupable(this->createPickup());
215    }
216
217    /**
218    @brief
219        Sets the maximum number of spawned items.
220    @param items
221        The maximum number of spawned items to be set.
222    */
223    void PickupSpawner::setMaxSpawnedItems(int items)
224    {
225        this->maxSpawnedItems_ = items;
226        this->spawnsRemaining_ = items;
227    }
228
229    /**
230    @brief
231        Decrements the number of remaining spawns.
232        Sets the PickupSpawner to inactive for the duration of the respawnTime.
233        Destroys the PickupSpawner if the number of remaining spawns has reached zero.
234    */
235    void PickupSpawner::decrementSpawnsRemaining(void)
236    {
237        if(this->spawnsRemaining_ != INF)
238            this->spawnsRemaining_--;
239
240        this->setActive(false);
241
242        if(this->spawnsRemaining_ != 0 && this->respawnTime_ > 0)
243        {
244            this->startRespawnTimer();
245            this->fireEvent();
246        }
247        else
248        {
249            orxout(verbose, context::pickups) << "PickupSpawner (&" << this << ") empty, selfdestruct initialized." << endl;
250            this->destroy();
251        }
252    }
253
254    /**
255    @brief
256        Starts the respawn timer.
257    */
258    void PickupSpawner::startRespawnTimer(void)
259    {
260        this->respawnTimer_.setTimer(this->respawnTime_, false, createExecutor(createFunctor(&PickupSpawner::respawnTimerCallback, this)));
261    }
262
263    /**
264    @brief
265        Invoked by the timer, re-activates the PickupSpawner.
266    */
267    void PickupSpawner::respawnTimerCallback()
268    {
269        orxout(verbose, context::pickups) << "PickupSpawner (&" << this << ") reactivated." << endl;
270
271        this->setPickupable(this->createPickup());
272    }
273
274    /**
275    @brief
276        Creates a new Pickupable.
277    @return
278        The Pickupable created.
279    */
280    Pickupable* PickupSpawner::createPickup(void)
281    {
282        if(this->spawnsRemaining_ == 0)
283        {
284            orxout(internal_error, context::pickups) << "Massive Error: PickupSpawner still alive until having spawned last item." << endl;
285            return nullptr;
286        }
287
288        if (this->pickupTemplate_ != nullptr)
289        {
290            Identifier* identifier = this->pickupTemplate_->getBaseclassIdentifier();
291            if (identifier != nullptr)
292            {
293                Pickupable* pickup = orxonox_cast<Pickupable*>(identifier->fabricate(this->getContext()));
294                orxonox_cast<BaseObject*>(pickup)->addTemplate(this->pickupTemplate_);
295                return pickup;
296            }
297            else
298                orxout(internal_error, context::pickups) << "No base class defined in pickup-template " << this->pickupTemplateName_ << endl;
299        }
300
301        return nullptr;
302    }
303
304    /**
305    @brief
306        Sets a Pickupable for the PickupSpawner to spawn.
307    @param pickup
308        The Pickupable to be set.
309    */
310    void PickupSpawner::setPickupable(Pickupable* pickup)
311    {
312        if (this->representation_ != nullptr)
313        {
314            this->representation_->destroy();
315            this->representation_ = nullptr;
316        }
317
318        if (pickup != nullptr)
319        {
320            if (this->pickup_ != nullptr)
321                this->pickup_->destroy();
322
323            PickupRepresentation* representation = PickupManager::getInstance().getRepresentation(pickup->getRepresentationName());
324            this->representation_ = representation->createSpawnerRepresentation(this);
325            this->attach(this->representation_);
326            this->setActive(true);
327        }
328        else
329        {
330            this->setActive(false);
331        }
332
333        this->pickup_ = pickup;
334    }
335}
Note: See TracBrowser for help on using the repository browser.