Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/modules/pickup/items/HealthPickup.cc @ 12105

Last change on this file since 12105 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
RevLine 
[6474]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
[6540]29/**
30    @file HealthPickup.cc
31    @brief Implementation of the HealthPickup class.
32*/
33
[6474]34#include "HealthPickup.h"
35
[7547]36#include <sstream>
[6474]37#include "core/CoreIncludes.h"
38#include "core/XMLPort.h"
39
40#include "worldentities/pawns/Pawn.h"
41
42namespace orxonox
43{
[7163]44
[6474]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";
[7163]48
[9667]49    RegisterClass(HealthPickup);
[7163]50
[6477]51    /**
52    @brief
53        Constructor. Registers the object and initializes the member variables.
54    */
[9667]55    HealthPickup::HealthPickup(Context* context) : Pickup(context)
[6474]56    {
57        RegisterObject(HealthPickup);
[7163]58
[6474]59        this->initialize();
60    }
[7163]61
[6477]62    /**
63    @brief
64        Destructor.
65    */
[6474]66    HealthPickup::~HealthPickup()
67    {
[7163]68
[6474]69    }
[7163]70
[6477]71    /**
[7163]72    @brief
[6477]73        Initializes the member variables.
74    */
[6474]75    void HealthPickup::initialize(void)
[7163]76    {
[8864]77        this->health_ = 0.0f;
78        this->healthRate_ = 0.0f;
[11071]79        this->healthType_ = PickupHealthType::limited;
[8864]80        this->maxHealthSave_ = 0.0f;
81        this->maxHealthOverwrite_ = 0.0f;
[7163]82
[6490]83        this->addTarget(ClassIdentifier<Pawn>::getIdentifier());
[6474]84    }
[7163]85
[6477]86    /**
87    @brief
88        Method for creating a HealthPickup object through XML.
89    */
[6496]90    void HealthPickup::XMLPort(Element& xmlelement, orxonox::XMLPort::Mode mode)
[6474]91    {
92        SUPER(HealthPickup, XMLPort, xmlelement, mode);
[7163]93
[6474]94        XMLPortParam(HealthPickup, "health", setHealth, getHealth, xmlelement, mode);
[6477]95        XMLPortParam(HealthPickup, "healthRate", setHealthRate, getHealthRate, xmlelement, mode);
[9348]96        XMLPortParam(HealthPickup, "healthType", setHealthTypeAsString, getHealthTypeAsString, xmlelement, mode);
[7163]97
[6474]98        if(!this->isContinuous())
[9348]99            this->setHealthRate(0.0f); // TODO: this logic should be inside tick(), not in XMLPort
[6474]100    }
[7163]101
[6477]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    */
[6474]109    void HealthPickup::tick(float dt)
110    {
[6540]111        SUPER(HealthPickup, tick, dt);
[7163]112
[6474]113        if(this->isContinuous() && this->isUsed())
114        {
[6477]115            Pawn* pawn = this->carrierToPawnHelper();
[11071]116            if(pawn == nullptr) // If the PickupCarrier is no Pawn, then this pickup is useless and therefore is destroyed.
[7163]117                this->Pickupable::destroy();
118
[7541]119            // Calculate the health that is added this tick.
[6477]120            float health = dt*this->getHealthRate();
[6474]121            if(health > this->getHealth())
122                health = this->getHealth();
[7541]123            // Calculate the health the Pawn will have once the health is added.
[6474]124            float fullHealth = pawn->getHealth() + health;
125            this->setHealth(this->getHealth()-health);
[7163]126
[9348]127            switch(this->getHealthType())
[6474]128            {
[11071]129                case PickupHealthType::permanent:
[6520]130                    if(pawn->getMaxHealth() < fullHealth)
[6474]131                        pawn->setMaxHealth(fullHealth);
[11071]132                case PickupHealthType::limited:
[6474]133                    pawn->addHealth(health);
134                    break;
[11071]135                case PickupHealthType::temporary:
[6477]136                    if(pawn->getMaxHealth() > fullHealth)
137                    {
138                        this->maxHealthSave_ = pawn->getMaxHealth();
139                        this->maxHealthOverwrite_ = fullHealth;
140                        pawn->setMaxHealth(fullHealth);
141                    }
142                    pawn->addHealth(health);
[6474]143                    break;
144                default:
[8858]145                    orxout(internal_error, context::pickups) << "Invalid healthType in HealthPickup." << endl;
[6474]146            }
[7163]147
[7541]148            // If all health has been transferred.
[8864]149            if(this->getHealth() == 0.0f)
[6474]150            {
[6477]151                this->setUsed(false);
[6474]152            }
153        }
154    }
[7163]155
[6477]156    /**
157    @brief
158        Is called when the pickup has transited from used to unused or the other way around.
159    */
[6474]160    void HealthPickup::changedUsed(void)
161    {
162        SUPER(HealthPickup, changedUsed);
[7163]163
[7541]164        // If the pickup has transited to used.
[6474]165        if(this->isUsed())
166        {
167            if(this->isOnce())
168            {
[6477]169                Pawn* pawn = this->carrierToPawnHelper();
[11071]170                if(pawn == nullptr) // If the PickupCarrier is no Pawn, then this pickup is useless and therefore is destroyed.
[7163]171                    this->Pickupable::destroy();
172
[8864]173                float health = 0.0f;
[9348]174                switch(this->getHealthType())
[6474]175                {
[11071]176                    case PickupHealthType::permanent:
[6474]177                        health = pawn->getHealth()+this->getHealth();
178                        if(pawn->getMaxHealth() < health)
179                            pawn->setMaxHealth(health);
[11071]180                    case PickupHealthType::limited:
[6474]181                        pawn->addHealth(this->getHealth());
182                        break;
[11071]183                    case PickupHealthType::temporary:
[6477]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());
[6474]192                        break;
193                    default:
[8858]194                        orxout(internal_error, context::pickups) << "Invalid healthType in HealthPickup." << endl;
[6474]195                }
[7163]196
[7541]197                // The pickup has been used up.
[6477]198                this->setUsed(false);
[6474]199            }
200        }
201        else
202        {
[11071]203            if(this->getHealthType() == PickupHealthType::temporary)
[6477]204            {
205                PickupCarrier* carrier = this->getCarrier();
[9348]206                Pawn* pawn = orxonox_cast<Pawn*>(carrier);
[7163]207
[11071]208                if(pawn == nullptr)
[6477]209                {
[8864]210                    orxout(internal_error, context::pickups) << "Something went horribly wrong in Health Pickup. PickupCarrier is '" << carrier->getIdentifier()->getName() << "' instead of Pawn." << endl;
[7163]211                    this->Pickupable::destroy();
[6477]212                    return;
213                }
[7163]214
[6477]215                if(pawn->getMaxHealth() == this->maxHealthOverwrite_)
216                {
217                    pawn->setMaxHealth(this->maxHealthSave_);
218                    this->maxHealthOverwrite_ = 0;
219                    this->maxHealthSave_ = 0;
220                }
221            }
[7163]222
[7541]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.
[8864]224            if(this->isOnce() || (this->isContinuous() && this->getHealth() == 0.0f))
[6477]225            {
[7163]226                this->Pickupable::destroy();
[6477]227            }
[6474]228        }
229    }
[7163]230
[6477]231    /**
232    @brief
233        Helper to transform the PickupCarrier to a Pawn, and throw an error message if the conversion fails.
234    @return
[11071]235        A pointer to the Pawn, or nullptr if the conversion failed.
[6477]236    */
237    Pawn* HealthPickup::carrierToPawnHelper(void)
238    {
239        PickupCarrier* carrier = this->getCarrier();
[9348]240        Pawn* pawn = orxonox_cast<Pawn*>(carrier);
[7163]241
[11071]242        if(pawn == nullptr)
[8858]243            orxout(internal_error, context::pickups) << "Invalid PickupCarrier in HealthPickup." << endl;
[7163]244
[6477]245        return pawn;
246    }
[7163]247
[6477]248    /**
249    @brief
250        Get the health type of this pickup.
251    @return
252        Returns the health type as a string.
253    */
[9348]254    const std::string& HealthPickup::getHealthTypeAsString(void) const
[6477]255    {
[9348]256        switch(this->getHealthType())
[6477]257        {
[11071]258            case PickupHealthType::limited:
[6477]259                return HealthPickup::healthTypeLimited_s;
[11071]260            case PickupHealthType::temporary:
[6477]261                return HealthPickup::healthTypeTemporary_s;
[11071]262            case PickupHealthType::permanent:
[6477]263                return HealthPickup::healthTypePermanent_s;
264            default:
[8858]265                orxout(internal_error, context::pickups) << "Invalid healthType in HealthPickup." << endl;
[6477]266                return BLANKSTRING;
267        }
268    }
[7163]269
[6477]270    /**
271    @brief
272        Sets the health.
273    @param health
274        The health.
275    */
276    void HealthPickup::setHealth(float health)
277    {
[6499]278        if(health >= 0.0f)
[6477]279            this->health_ = health;
280        else
281        {
[8864]282            orxout(internal_error, context::pickups) << "Invalid health '" << health << "' in HealthPickup. The health must be non.negative." << endl;
283            this->health_ = 0.0f;
[6477]284        }
285    }
[7163]286
[6477]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    {
[8864]295        if(rate >= 0.0f)
[6477]296            this->healthRate_ = rate;
297        else
[8864]298            orxout(internal_error, context::pickups) << "Invalid healthRate '" << rate << "' in HealthPickup. The healthRate must be non-negative." << endl;
[6477]299    }
[7163]300
[6477]301    /**
302    @brief
303        Set the type of the HealthPickup.
304    @param type
305        The type as a string.
306    */
[9348]307    void HealthPickup::setHealthTypeAsString(const std::string& type)
[6477]308    {
309        if(type == HealthPickup::healthTypeLimited_s)
[11071]310            this->setHealthType(PickupHealthType::limited);
[6477]311        else if(type == HealthPickup::healthTypeTemporary_s)
[11071]312            this->setHealthType(PickupHealthType::temporary);
[6477]313        else if(type == HealthPickup::healthTypePermanent_s)
[11071]314            this->setHealthType(PickupHealthType::permanent);
[6477]315        else
[8864]316            orxout(internal_error, context::pickups) << "Invalid healthType '" << type << "' in HealthPickup." << endl;
[6477]317    }
[6474]318
319}
Note: See TracBrowser for help on using the repository browser.