Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/presentation2012merge/src/modules/pickup/items/HealthPickup.cc @ 9319

Last change on this file since 9319 was 9318, checked in by landauf, 13 years ago

removed PickupIdentifier for a number of reasons (I talked to Damian about it before)
a pickup now references the PickupRepresentation by name with the "representation" attribute

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