Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/mergeFS18/src/modules/pickup/items/HealthPickup.cc

Last change on this file was 11071, checked in by landauf, 9 years ago

merged branch cpp11_v3 back to trunk

  • Property svn:eol-style set to native
File size: 10.5 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    RegisterClass(HealthPickup);
50
51    /**
52    @brief
53        Constructor. Registers the object and initializes the member variables.
54    */
55    HealthPickup::HealthPickup(Context* context) : Pickup(context)
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 == nullptr) // 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 == nullptr) // 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 == nullptr)
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 nullptr 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 == nullptr)
243            orxout(internal_error, context::pickups) << "Invalid PickupCarrier in HealthPickup." << endl;
244
245        return pawn;
246    }
247
248    /**
249    @brief
250        Get the health type of this pickup.
251    @return
252        Returns the health type as a string.
253    */
254    const std::string& HealthPickup::getHealthTypeAsString(void) const
255    {
256        switch(this->getHealthType())
257        {
258            case PickupHealthType::limited:
259                return HealthPickup::healthTypeLimited_s;
260            case PickupHealthType::temporary:
261                return HealthPickup::healthTypeTemporary_s;
262            case PickupHealthType::permanent:
263                return HealthPickup::healthTypePermanent_s;
264            default:
265                orxout(internal_error, context::pickups) << "Invalid healthType in HealthPickup." << endl;
266                return BLANKSTRING;
267        }
268    }
269
270    /**
271    @brief
272        Sets the health.
273    @param health
274        The health.
275    */
276    void HealthPickup::setHealth(float health)
277    {
278        if(health >= 0.0f)
279            this->health_ = health;
280        else
281        {
282            orxout(internal_error, context::pickups) << "Invalid health '" << health << "' in HealthPickup. The health must be non.negative." << endl;
283            this->health_ = 0.0f;
284        }
285    }
286
287    /**
288    @brief
289        Set the rate at which health is transferred if the pickup is continuous.
290    @param rate
291        The rate.
292    */
293    void HealthPickup::setHealthRate(float rate)
294    {
295        if(rate >= 0.0f)
296            this->healthRate_ = rate;
297        else
298            orxout(internal_error, context::pickups) << "Invalid healthRate '" << rate << "' in HealthPickup. The healthRate must be non-negative." << endl;
299    }
300
301    /**
302    @brief
303        Set the type of the HealthPickup.
304    @param type
305        The type as a string.
306    */
307    void HealthPickup::setHealthTypeAsString(const std::string& type)
308    {
309        if(type == HealthPickup::healthTypeLimited_s)
310            this->setHealthType(PickupHealthType::limited);
311        else if(type == HealthPickup::healthTypeTemporary_s)
312            this->setHealthType(PickupHealthType::temporary);
313        else if(type == HealthPickup::healthTypePermanent_s)
314            this->setHealthType(PickupHealthType::permanent);
315        else
316            orxout(internal_error, context::pickups) << "Invalid healthType '" << type << "' in HealthPickup." << endl;
317    }
318
319}
Note: See TracBrowser for help on using the repository browser.