Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/presentation3/src/modules/pickup/items/HealthPickup.cc @ 7162

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

Significant structural changes to the pickup module. Lots of bugs found and fixed.
Introduced a new class CollectiblePickup (which is now the only kind a PickupCollection can consist of) to solve some issues cleanly.
MetaPickup received additional functionality. It can now also be set to either destroy all the pickups of a PickupCarrier or destroy the PickupCarrier itself. (This was done mainly for testing purposes)
I've done some extensive testing on the pickups, so they should really work now.

  • Property svn:eol-style set to native
File size: 11.7 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 *      Damian 'Mozork' Frick
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29/**
30    @file HealthPickup.cc
31    @brief Implementation of the HealthPickup class.
32*/
33
34#include "HealthPickup.h"
35
36#include "core/CoreIncludes.h"
37#include "core/XMLPort.h"
38#include "util/StringUtils.h"
39
40#include "worldentities/pawns/Pawn.h"
41#include "pickup/PickupIdentifier.h"
42
43#include <sstream>
44
45namespace orxonox
46{
47
48    /*static*/ const std::string HealthPickup::healthTypeLimited_s = "limited";
49    /*static*/ const std::string HealthPickup::healthTypeTemporary_s = "temporary";
50    /*static*/ const std::string HealthPickup::healthTypePermanent_s = "permanent";
51
52    CreateFactory(HealthPickup);
53
54    /**
55    @brief
56        Constructor. Registers the object and initializes the member variables.
57    */
58    HealthPickup::HealthPickup(BaseObject* creator) : Pickup(creator)
59    {
60        RegisterObject(HealthPickup);
61
62        this->initialize();
63    }
64
65    /**
66    @brief
67        Destructor.
68    */
69    HealthPickup::~HealthPickup()
70    {
71
72    }
73
74    /**
75    @brief
76        Initializes the member variables.
77    */
78    void HealthPickup::initialize(void)
79    {
80        this->health_ = 0;
81        this->healthRate_ = 0;
82        this->healthType_ = pickupHealthType::limited;
83        this->maxHealthSave_ = 0;
84        this->maxHealthOverwrite_ = 0;
85
86        this->addTarget(ClassIdentifier<Pawn>::getIdentifier());
87    }
88
89    /**
90    @brief
91        Initializes the PickupIdentifier of this pickup.
92    */
93    void HealthPickup::initializeIdentifier(void)
94    {
95        std::stringstream stream;
96        stream << this->getHealth();
97        std::string type1 = "health";
98        std::string val1 = stream.str();
99        this->pickupIdentifier_->addParameter(type1, val1);
100
101        std::string val2 = this->getHealthType();
102        std::string type2 = "healthType";
103        this->pickupIdentifier_->addParameter(type2, val2);
104
105        stream.clear();
106        stream << this->getHealthRate();
107        std::string val3 = stream.str();
108        std::string type3 = "healthRate";
109        this->pickupIdentifier_->addParameter(type3, val3);
110    }
111
112    /**
113    @brief
114        Method for creating a HealthPickup object through XML.
115    */
116    void HealthPickup::XMLPort(Element& xmlelement, orxonox::XMLPort::Mode mode)
117    {
118        SUPER(HealthPickup, XMLPort, xmlelement, mode);
119
120        XMLPortParam(HealthPickup, "health", setHealth, getHealth, xmlelement, mode);
121        XMLPortParam(HealthPickup, "healthRate", setHealthRate, getHealthRate, xmlelement, mode);
122        XMLPortParam(HealthPickup, "healthType", setHealthType, getHealthType, xmlelement, mode);
123
124        if(!this->isContinuous())
125            this->healthRate_ = 0.0;
126
127        this->initializeIdentifier();
128    }
129
130    /**
131    @brief
132        Is called every tick.
133        Does all the continuous stuff of this HealthPickup.
134    @param dt
135        The duration of the last tick.
136    */
137    void HealthPickup::tick(float dt)
138    {
139        SUPER(HealthPickup, tick, dt);
140
141        if(this->isContinuous() && this->isUsed())
142        {
143            Pawn* pawn = this->carrierToPawnHelper();
144            if(pawn == NULL) //!< If the PickupCarrier is no Pawn, then this pickup is useless and therefore is destroyed.
145                this->Pickupable::destroy();
146
147            //! Calculate the health that is added this tick.
148            float health = dt*this->getHealthRate();
149            if(health > this->getHealth())
150                health = this->getHealth();
151            //! Calculate the health the Pawn will have once the health is added.
152            float fullHealth = pawn->getHealth() + health;
153            this->setHealth(this->getHealth()-health);
154
155            switch(this->getHealthTypeDirect())
156            {
157                case pickupHealthType::permanent:
158                    if(pawn->getMaxHealth() < fullHealth)
159                        pawn->setMaxHealth(fullHealth);
160                case pickupHealthType::limited:
161                    pawn->addHealth(health);
162                    break;
163                case pickupHealthType::temporary:
164                    if(pawn->getMaxHealth() > fullHealth)
165                    {
166                        this->maxHealthSave_ = pawn->getMaxHealth();
167                        this->maxHealthOverwrite_ = fullHealth;
168                        pawn->setMaxHealth(fullHealth);
169                    }
170                    pawn->addHealth(health);
171                    break;
172                default:
173                    COUT(1) << "Invalid healthType in HealthPickup." << std::endl;
174            }
175
176            //! If all health has been transfered.
177            if(this->getHealth() == 0)
178            {
179                this->setUsed(false);
180            }
181        }
182    }
183
184    /**
185    @brief
186        Is called when the pickup has transited from used to unused or the other way around.
187    */
188    void HealthPickup::changedUsed(void)
189    {
190        SUPER(HealthPickup, changedUsed);
191
192        //! If the pickup is not picked up nothing must be done.
193        if(!this->isPickedUp()) //TODO: Needed?
194            return;
195
196        //! If the pickup has transited to used.
197        if(this->isUsed())
198        {
199            if(this->isOnce())
200            {
201                Pawn* pawn = this->carrierToPawnHelper();
202                if(pawn == NULL) //!< If the PickupCarrier is no Pawn, then this pickup is useless and therefore is destroyed.
203                    this->Pickupable::destroy();
204
205                float health = 0;
206                switch(this->getHealthTypeDirect())
207                {
208                    case pickupHealthType::permanent:
209                        health = pawn->getHealth()+this->getHealth();
210                        if(pawn->getMaxHealth() < health)
211                            pawn->setMaxHealth(health);
212                    case pickupHealthType::limited:
213                        pawn->addHealth(this->getHealth());
214                        break;
215                    case pickupHealthType::temporary:
216                        health = pawn->getHealth()+this->getHealth();
217                        if(pawn->getMaxHealth() < health)
218                        {
219                            this->maxHealthSave_ = pawn->getMaxHealth();
220                            this->maxHealthOverwrite_ = health;
221                            pawn->setMaxHealth(health);
222                        }
223                        pawn->addHealth(this->getHealth());
224                        break;
225                    default:
226                        COUT(1) << "Invalid healthType in HealthPickup." << std::endl;
227                }
228
229                //! The pickup has been used up.
230                this->setUsed(false);
231            }
232        }
233        else
234        {
235            if(this->getHealthTypeDirect() == pickupHealthType::temporary)
236            {
237                PickupCarrier* carrier = this->getCarrier();
238                Pawn* pawn = dynamic_cast<Pawn*>(carrier);
239
240                if(pawn == NULL)
241                {
242                    COUT(1) << "Something went horribly wrong in Health Pickup. PickupCarrier is no Pawn." << std::endl;
243                    this->Pickupable::destroy();
244                    return;
245                }
246
247                if(pawn->getMaxHealth() == this->maxHealthOverwrite_)
248                {
249                    pawn->setMaxHealth(this->maxHealthSave_);
250                    this->maxHealthOverwrite_ = 0;
251                    this->maxHealthSave_ = 0;
252                }
253            }
254
255            //! If either the pickup can only be used once or it is continuous and used up, it is destroyed upon setting it to unused.
256            if(this->isOnce() || (this->isContinuous() && this->getHealth() == 0))
257            {
258                this->Pickupable::destroy();
259            }
260        }
261    }
262
263    /**
264    @brief
265        Helper to transform the PickupCarrier to a Pawn, and throw an error message if the conversion fails.
266    @return
267        A pointer to the Pawn, or NULL if the conversion failed.
268    */
269    Pawn* HealthPickup::carrierToPawnHelper(void)
270    {
271        PickupCarrier* carrier = this->getCarrier();
272        Pawn* pawn = dynamic_cast<Pawn*>(carrier);
273
274        if(pawn == NULL)
275        {
276            COUT(1) << "Invalid PickupCarrier in HealthPickup." << std::endl;
277        }
278
279        return pawn;
280    }
281
282    /**
283    @brief
284        Creates a duplicate of the input OrxonoxClass.
285    @param item
286        A pointer to the Orxonox class.
287    */
288    void HealthPickup::clone(OrxonoxClass*& item)
289    {
290        if(item == NULL)
291            item = new HealthPickup(this);
292
293        SUPER(HealthPickup, clone, item);
294
295        HealthPickup* pickup = dynamic_cast<HealthPickup*>(item);
296        pickup->setHealth(this->getHealth());
297        pickup->setHealthRate(this->getHealthRate());
298        pickup->setHealthTypeDirect(this->getHealthTypeDirect());
299
300        pickup->initializeIdentifier();
301    }
302
303    /**
304    @brief
305        Get the health type of this pickup.
306    @return
307        Returns the health type as a string.
308    */
309    const std::string& HealthPickup::getHealthType(void)
310    {
311        switch(this->getHealthTypeDirect())
312        {
313            case pickupHealthType::limited:
314                return HealthPickup::healthTypeLimited_s;
315            case pickupHealthType::temporary:
316                return HealthPickup::healthTypeTemporary_s;
317            case pickupHealthType::permanent:
318                return HealthPickup::healthTypePermanent_s;
319            default:
320                COUT(1) << "Invalid healthType in HealthPickup." << std::endl;
321                return BLANKSTRING;
322        }
323    }
324
325    /**
326    @brief
327        Sets the health.
328    @param health
329        The health.
330    */
331    void HealthPickup::setHealth(float health)
332    {
333        if(health >= 0.0f)
334        {
335            this->health_ = health;
336        }
337        else
338        {
339            COUT(1) << "Invalid health in HealthPickup." << std::endl;
340            this->health_ = 0.0;
341        }
342    }
343
344    /**
345    @brief
346        Set the rate at which health is transferred if the pickup is continuous.
347    @param rate
348        The rate.
349    */
350    void HealthPickup::setHealthRate(float rate)
351    {
352        if(rate >= 0)
353        {
354            this->healthRate_ = rate;
355        }
356        else
357        {
358            COUT(1) << "Invalid healthSpeed in HealthPickup." << std::endl;
359        }
360    }
361
362    /**
363    @brief
364        Set the type of the HealthPickup.
365    @param type
366        The type as a string.
367    */
368    void HealthPickup::setHealthType(std::string type)
369    {
370        if(type == HealthPickup::healthTypeLimited_s)
371        {
372            this->setHealthTypeDirect(pickupHealthType::limited);
373        }
374        else if(type == HealthPickup::healthTypeTemporary_s)
375        {
376            this->setHealthTypeDirect(pickupHealthType::temporary);
377        }
378        else if(type == HealthPickup::healthTypePermanent_s)
379        {
380            this->setHealthTypeDirect(pickupHealthType::permanent);
381        }
382        else
383        {
384            COUT(1) << "Invalid healthType in HealthPickup." << std::endl;
385        }
386    }
387
388}
Note: See TracBrowser for help on using the repository browser.