Index: code/branches/pickup3/src/modules/pickup/items/HealthPickup.cc
===================================================================
--- code/branches/pickup3/src/modules/pickup/items/HealthPickup.cc	(revision 6475)
+++ code/branches/pickup3/src/modules/pickup/items/HealthPickup.cc	(revision 6477)
@@ -31,4 +31,5 @@
 #include "core/CoreIncludes.h"
 #include "core/XMLPort.h"
+#include "util/StringUtils.h"
 
 #include "worldentities/pawns/Pawn.h"
@@ -43,8 +44,11 @@
     /*static*/ const std::string HealthPickup::healthTypeTemporary_s = "temporary";
     /*static*/ const std::string HealthPickup::healthTypePermanent_s = "permanent";
-    /*static*/ const std::string HealthPickup::blankString_s = "";
     
     CreateFactory(HealthPickup);
     
+    /**
+    @brief
+        Constructor. Registers the object and initializes the member variables.
+    */
     HealthPickup::HealthPickup(BaseObject* creator) : Pickup(creator)
     {
@@ -54,4 +58,8 @@
     }
     
+    /**
+    @brief
+        Destructor.
+    */
     HealthPickup::~HealthPickup()
     {
@@ -59,4 +67,8 @@
     }
     
+    /**
+    @brief 
+        Initializes the member variables.
+    */
     void HealthPickup::initialize(void)
     {
@@ -64,9 +76,15 @@
         
         this->health_ = 0;
-        this->healthSpeed_ = 0;
+        this->healthRate_ = 0;
         this->healthType_ = pickupHealthType::limited;
-        
-    }
-    
+        this->maxHealthSave_ = 0;
+        this->maxHealthOverwrite_ = 0;
+        
+    }
+    
+    /**
+    @brief
+        Initializes the PickupIdentifier of this pickup.
+    */
     void HealthPickup::initializeIdentifier(void)
     {
@@ -83,6 +101,16 @@
         std::string type2 = "healthType";
         this->pickupIdentifier_->addParameter(type2, val2);
-    }
-    
+        
+        stream.clear();
+        stream << this->getHealthRate();
+        std::string val3 = stream.str();
+        std::string type3 = "healthRate";
+        this->pickupIdentifier_->addParameter(type3, val3);
+    }
+    
+    /**
+    @brief
+        Method for creating a HealthPickup object through XML.
+    */
     void HealthPickup::HealthPickup::XMLPort(Element& xmlelement, orxonox::XMLPort::Mode mode)
     {
@@ -90,73 +118,33 @@
         
         XMLPortParam(HealthPickup, "health", setHealth, getHealth, xmlelement, mode);
-        XMLPortParam(HealthPickup, "healthSpeed", setHealthSpeed, getHealthSpeed, xmlelement, mode);
+        XMLPortParam(HealthPickup, "healthRate", setHealthRate, getHealthRate, xmlelement, mode);
         XMLPortParam(HealthPickup, "healthType", setHealthType, getHealthType, xmlelement, mode);
         
         if(!this->isContinuous())
-            this->healthSpeed_ = 0.0;
+            this->healthRate_ = 0.0;
         
         this->initializeIdentifier();
     }
     
-    void HealthPickup::setHealth(float health)
-    {
-        if(health > 0.0f)
-        {
-            this->health_ = health;
-        }
-        else
-        {
-            COUT(1) << "Invalid health in HealthPickup." << std::endl;
-        }
-    }
-    
-    void HealthPickup::setHealthSpeed(float speed)
-    {
-        if(speed >= 0)
-        {
-            this->healthSpeed_ = speed;
-        }
-        else
-        {
-            COUT(1) << "Invalid healthSpeed in HealthPickup." << std::endl; 
-        }
-    }
-    
-    void HealthPickup::setHealthType(std::string type)
-    {
-        if(type == HealthPickup::healthTypeLimited_s)
-        {
-            this->setHealthTypeDirect(pickupHealthType::limited);
-        }
-        else if(type == HealthPickup::healthTypeTemporary_s)
-        {
-            this->setHealthTypeDirect(pickupHealthType::temporary);
-        }
-        else if(type == HealthPickup::healthTypePermanent_s)
-        {
-            this->setHealthTypeDirect(pickupHealthType::permanent);
-        }
-        else
-        {
-            COUT(1) << "Invalid healthType in HealthPickup." << std::endl;
-        }
-    }
-    
+    /**
+    @brief
+        Is called every tick.
+        Does all the continuous stuff of this HealthPickup.
+    @param dt
+        The duration of the last tick.
+    */
     void HealthPickup::tick(float dt)
     {
         if(this->isContinuous() && this->isUsed())
         {
-            PickupCarrier* carrier = this->getCarrier();
-            Pawn* pawn = dynamic_cast<Pawn*>(carrier);
+            Pawn* pawn = this->carrierToPawnHelper();
+            if(pawn == NULL) //!< If the PickupCarrier is no Pawn, then this pickup is useless and therefore is destroyed.
+                this->destroy();
             
-            if(pawn == NULL)
-            {
-                COUT(1) << "Invalid PickupCarrier in HealthPickup." << std::endl;
-                return;
-            }
-            
-            float health = dt*this->getHealthSpeed();
+            //! Calculate the health that is added this tick.
+            float health = dt*this->getHealthRate();
             if(health > this->getHealth())
                 health = this->getHealth();
+            //! Calculate the health the Pawn will have once the health is added.
             float fullHealth = pawn->getHealth() + health;
             this->setHealth(this->getHealth()-health);
@@ -171,5 +159,11 @@
                     break;
                 case pickupHealthType::temporary:
-                    //TODO: How?
+                    if(pawn->getMaxHealth() > fullHealth)
+                    {
+                        this->maxHealthSave_ = pawn->getMaxHealth();
+                        this->maxHealthOverwrite_ = fullHealth;
+                        pawn->setMaxHealth(fullHealth);
+                    }
+                    pawn->addHealth(health);
                     break;
                 default:
@@ -177,61 +171,33 @@
             }
             
+            //! If all health has been transfered.
             if(this->getHealth() == 0)
             {
-                //TODO: Destroy
-            }
-        }
-    }
-    
-    const std::string& HealthPickup::getHealthType(void)
-    {
-        switch(this->getHealthTypeDirect())
-        {
-            case pickupHealthType::limited:
-                return HealthPickup::healthTypeLimited_s;
-            case pickupHealthType::temporary:
-                return HealthPickup::healthTypeTemporary_s;
-            case pickupHealthType::permanent:
-                return HealthPickup::healthTypePermanent_s;
-            default:
-                COUT(1) << "Invalid healthType in HealthPickup." << std::endl;
-                return HealthPickup::blankString_s;
-        }
-    }
-    
-    void HealthPickup::clone(OrxonoxClass* item)
-    {
-        if(item == NULL)
-            item = new HealthPickup(this);
-        
-        SUPER(HealthPickup, clone, item);
-        
-        //TODO: No temp needed?
-        HealthPickup* pickup = dynamic_cast<HealthPickup*>(item);
-        pickup->setHealth(this->getHealth());
-        pickup->setHealthSpeed(this->getHealthSpeed());
-        pickup->setHealthTypeDirect(this->getHealthTypeDirect());
-        
-        pickup->initializeIdentifier();
-    }
-    
-    //TODO: Does this work even if Pickup doesn't implement it?
+                this->setUsed(false);
+            }
+        }
+    }
+    
+    /**
+    @brief
+        Is called when the pickup has transited from used to unused or the other way around.
+    */
     void HealthPickup::changedUsed(void)
     {
         SUPER(HealthPickup, changedUsed);
         
+        //! If the pickup is not picked up nothing must be done.
+        if(!this->isPickedUp())
+            return;
+        
+        //! If the pickup has transited to used.
         if(this->isUsed())
         {
-            PickupCarrier* carrier = this->getCarrier();
-            Pawn* pawn = dynamic_cast<Pawn*>(carrier);
-            
-            if(pawn == NULL)
-            {
-                COUT(1) << "Invalid PickupCarrier in HealthPickup." << std::endl;
-                return;
-            }
-            
             if(this->isOnce())
             {
+                Pawn* pawn = this->carrierToPawnHelper();
+                if(pawn == NULL) //!< If the PickupCarrier is no Pawn, then this pickup is useless and therefore is destroyed.
+                    this->destroy();
+                
                 float health = 0;
                 switch(this->getHealthTypeDirect())
@@ -245,5 +211,12 @@
                         break;
                     case pickupHealthType::temporary:
-                        //TODO: How?
+                        health = pawn->getHealth()+this->getHealth();
+                        if(pawn->getMaxHealth() < health)
+                        {
+                            this->maxHealthSave_ = pawn->getMaxHealth();
+                            this->maxHealthOverwrite_ = health;
+                            pawn->setMaxHealth(health);
+                        }
+                        pawn->addHealth(this->getHealth());
                         break;
                     default:
@@ -251,10 +224,160 @@
                 }
                 
-                //TODO: Destroy.
+                //! The pickup has been used up.
+                this->setUsed(false);
             }
         }
         else
         {
-            //TODO: Destroy, but be careful to not destroy before being used.
+            if(this->getHealthTypeDirect() == pickupHealthType::temporary)
+            {
+                PickupCarrier* carrier = this->getCarrier();
+                Pawn* pawn = dynamic_cast<Pawn*>(carrier);
+                
+                if(pawn == NULL)
+                {
+                    COUT(1) << "Something went horribly wrong in Health Pickup. PickupCarrier is no Pawn." << std::endl;
+                    this->destroy();
+                    return;
+                }
+                
+                if(pawn->getMaxHealth() == this->maxHealthOverwrite_)
+                {
+                    pawn->setMaxHealth(this->maxHealthSave_);
+                    this->maxHealthOverwrite_ = 0;
+                    this->maxHealthSave_ = 0;
+                }
+            }
+            
+            //! If either the pickup can only be used once or it is continuous and used up, it is destroyed upon setting it to unused.
+            if(this->isOnce() || (this->isContinuous() && this->getHealth() == 0))
+            {
+                this->destroy();
+            }
+        }
+    }
+    
+    /**
+    @brief
+        Helper to transform the PickupCarrier to a Pawn, and throw an error message if the conversion fails.
+    @return
+        A pointer to the Pawn, or NULL if the conversion failed.
+    */
+    Pawn* HealthPickup::carrierToPawnHelper(void)
+    {
+        PickupCarrier* carrier = this->getCarrier();
+        Pawn* pawn = dynamic_cast<Pawn*>(carrier);
+        
+        if(pawn == NULL)
+        {
+            COUT(1) << "Invalid PickupCarrier in HealthPickup." << std::endl;
+        }
+        
+        return pawn;
+    }
+    
+    /**
+    @brief
+        Creates a duplicate of the input OrxonoxClass.
+    @param item
+        A pointer to the Orxonox class.
+    */
+    void HealthPickup::clone(OrxonoxClass* item)
+    {
+        if(item == NULL)
+            item = new HealthPickup(this);
+        
+        SUPER(HealthPickup, clone, item);
+        
+        HealthPickup* pickup = dynamic_cast<HealthPickup*>(item);
+        pickup->setHealth(this->getHealth());
+        pickup->setHealthRate(this->getHealthRate());
+        pickup->setHealthTypeDirect(this->getHealthTypeDirect());
+        
+        pickup->initializeIdentifier();
+    }
+    
+    /**
+    @brief
+        Get the health type of this pickup.
+    @return
+        Returns the health type as a string.
+    */
+    const std::string& HealthPickup::getHealthType(void)
+    {
+        switch(this->getHealthTypeDirect())
+        {
+            case pickupHealthType::limited:
+                return HealthPickup::healthTypeLimited_s;
+            case pickupHealthType::temporary:
+                return HealthPickup::healthTypeTemporary_s;
+            case pickupHealthType::permanent:
+                return HealthPickup::healthTypePermanent_s;
+            default:
+                COUT(1) << "Invalid healthType in HealthPickup." << std::endl;
+                return BLANKSTRING;
+        }
+    }
+    
+    /**
+    @brief
+        Sets the health.
+    @param health
+        The health.
+    */
+    void HealthPickup::setHealth(float health)
+    {
+        if(health > 0.0f)
+        {
+            this->health_ = health;
+        }
+        else
+        {
+            COUT(1) << "Invalid health in HealthPickup." << std::endl;
+            this->health_ = 0.0;
+        }
+    }
+    
+    /**
+    @brief
+        Set the rate at which health is transferred if the pickup is continuous.
+    @param rate
+        The rate.
+    */
+    void HealthPickup::setHealthRate(float rate)
+    {
+        if(rate >= 0)
+        {
+            this->healthRate_ = rate;
+        }
+        else
+        {
+            COUT(1) << "Invalid healthSpeed in HealthPickup." << std::endl; 
+        }
+    }
+    
+    /**
+    @brief
+        Set the type of the HealthPickup.
+    @param type
+        The type as a string.
+    */
+    void HealthPickup::setHealthType(std::string type)
+    {
+        if(type == HealthPickup::healthTypeLimited_s)
+        {
+            this->setHealthTypeDirect(pickupHealthType::limited);
+        }
+        else if(type == HealthPickup::healthTypeTemporary_s)
+        {
+            this->setHealthTypeDirect(pickupHealthType::temporary);
+        }
+        else if(type == HealthPickup::healthTypePermanent_s)
+        {
+            this->setHealthTypeDirect(pickupHealthType::permanent);
+        }
+        else
+        {
+            COUT(1) << "Invalid healthType in HealthPickup." << std::endl;
         }
     }
