Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/pickup3/src/modules/pickup/items/HealthPickup.cc @ 6497

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

Fixed bug in clone() (Argument needed to be as reference). Pickups seem to be working now (after very sporadic testing), more systematic testing (and probably still some more bug fixes) will follow.

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