Index: code/branches/presentationHS15/src/orxonox/weaponsystem/CMakeLists.txt
===================================================================
--- code/branches/presentationHS15/src/orxonox/weaponsystem/CMakeLists.txt	(revision 10959)
+++ code/branches/presentationHS15/src/orxonox/weaponsystem/CMakeLists.txt	(revision 10961)
@@ -1,4 +1,5 @@
 ADD_SOURCE_FILES(ORXONOX_SRC_FILES
   Munition.cc
+  ReplenishingMunition.cc
   Weapon.cc
   WeaponMode.cc
Index: code/branches/presentationHS15/src/orxonox/weaponsystem/Munition.cc
===================================================================
--- code/branches/presentationHS15/src/orxonox/weaponsystem/Munition.cc	(revision 10959)
+++ code/branches/presentationHS15/src/orxonox/weaponsystem/Munition.cc	(revision 10961)
@@ -24,5 +24,5 @@
  *      Fabian 'x3n' Landau
  *   Co-authors:
- *      ...
+ *      Fabien Vultier
  *
  */
@@ -32,4 +32,5 @@
 #include "core/CoreIncludes.h"
 #include "core/command/Executor.h"
+#include "core/XMLPort.h"
 
 namespace orxonox
@@ -43,23 +44,33 @@
         this->maxMunitionPerMagazine_ = 10;
         this->maxMagazines_ = 10;
-        this->magazines_ = 10;
-
-        this->bUseSeparateMagazines_ = false;
-        this->bStackMunition_ = true;
+        this->unassignedMagazines_ = 10;
+
+        this->deployment_ = MunitionDeployment::Stack;
         this->bAllowMunitionRefilling_ = true;
         this->bAllowMultiMunitionRemovementUnderflow_ = true;
 
-        this->reloadTime_ = 0;
+        this->reloadTime_ = 0.5f;
+
+        this->lastFilledWeaponMode_ = NULL;
     }
 
     Munition::~Munition()
     {
-        for (std::map<WeaponMode*, Magazine*>::iterator it = this->currentMagazines_.begin(); it != this->currentMagazines_.end(); ++it)
+        for (std::map<WeaponMode*, Magazine*>::iterator it = this->assignedMagazines_.begin(); it != this->assignedMagazines_.end(); ++it)
             delete it->second;
     }
 
+    void Munition::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(Munition, XMLPort, xmlelement, mode);
+
+        XMLPortParam(Munition, "initialmagazines", setNumMagazines, getNumMagazines, xmlelement, mode);
+        XMLPortParam(Munition, "maxmagazines", setMaxMagazines, getMaxMagazines, xmlelement, mode);
+        XMLPortParam(Munition, "munitionpermagazine", setMaxMunitionPerMagazine, getMaxMunitionPerMagazine, xmlelement, mode);
+    }
+
     Munition::Magazine* Munition::getMagazine(WeaponMode* user) const
     {
-        if (this->bUseSeparateMagazines_)
+        if (deployment_ == MunitionDeployment::Separate)
         {
             // For separated magazines we definitively need a given user
@@ -68,6 +79,6 @@
 
             // Use the map to get the magazine assigned to the given user
-            std::map<WeaponMode*, Magazine*>::const_iterator it = this->currentMagazines_.find(user);
-            if (it != this->currentMagazines_.end())
+            std::map<WeaponMode*, Magazine*>::const_iterator it = this->assignedMagazines_.find(user);
+            if (it != this->assignedMagazines_.end())
                 return it->second;
         }
@@ -75,6 +86,6 @@
         {
             // We don't use separate magazines for each user, so just take the first magazine
-            if (this->currentMagazines_.size() > 0)
-                return this->currentMagazines_.begin()->second;
+            if (this->assignedMagazines_.size() > 0)
+                return this->assignedMagazines_.begin()->second;
         }
 
@@ -87,7 +98,7 @@
         if (magazine)
         {
-            if (this->bStackMunition_)
+            if (deployment_ == MunitionDeployment::Stack)
                 // With stacked munition every magazine contributes to the total amount
-                return this->maxMunitionPerMagazine_ * this->magazines_ + magazine->munition_;
+                return this->maxMunitionPerMagazine_ * this->unassignedMagazines_ + magazine->munition_;
             else
                 // Wihtout stacked munition we just consider the current magazine
@@ -109,18 +120,23 @@
     unsigned int Munition::getNumMagazines() const
     {
-        if (this->bStackMunition_)
+        if (deployment_ == MunitionDeployment::Stack)
         {
             // If we stack munition and the current magazine is still full, it counts too
             Magazine* magazine = this->getMagazine(0);
             if (magazine && magazine->munition_ == this->maxMunitionPerMagazine_)
-                return this->magazines_ + 1;
-        }
-
-        return this->magazines_;
+                return this->unassignedMagazines_ + 1;
+        }
+
+        return this->unassignedMagazines_;
+    }
+
+    void Munition::setNumMagazines(unsigned int numMagazines)
+    {
+        this->unassignedMagazines_ = numMagazines;
     }
 
     unsigned int Munition::getMaxMunition() const
     {
-        if (this->bStackMunition_)
+        if (deployment_ == MunitionDeployment::Stack)
             return this->maxMunitionPerMagazine_ * this->maxMagazines_;
         else
@@ -135,17 +151,26 @@
             unsigned int munition = magazine->munition_;
 
-            // If we stack munition, we con't care about the current magazine - we just need enough munition in total
-            if (this->bStackMunition_)
-                munition += this->maxMunitionPerMagazine_ * this->magazines_;
+            // If we stack munition, we don't care about the current magazine - we just need enough munition in total
+            if (deployment_ == MunitionDeployment::Stack)
+            {
+                munition += this->maxMunitionPerMagazine_ * this->unassignedMagazines_;
+            }
 
             if (munition == 0)
+            {
                 // Absolutely no munition - no chance to take munition
                 return false;
+            }
             else if (this->bAllowMultiMunitionRemovementUnderflow_)
+            {
                 // We're not empty AND we allow underflow, so this will always work
                 return true;
+            }
             else
+            {
                 // We don't allow underflow, so we have to check the amount
                 return (munition >= amount);
+            }
+
         }
         return false;
@@ -169,5 +194,5 @@
             {
                 // Not enough munition
-                if (this->bStackMunition_)
+                if (deployment_ == MunitionDeployment::Stack)
                 {
                     // We stack munition, so just take what we can and then load the next magazine
@@ -175,5 +200,5 @@
                     magazine->munition_ = 0;
 
-                    if (this->reload(0))
+                    if (this->reload(NULL))
                         // Successfully reloaded, continue recursively
                         return this->takeMunition(amount, 0);
@@ -199,5 +224,5 @@
     {
         // As long as we have enough magazines (and don't stack munition) we can reload
-        return (this->magazines_ > 0 && !this->bStackMunition_);
+        return (this->unassignedMagazines_ > 0 && deployment_ != MunitionDeployment::Stack);
     }
 
@@ -207,5 +232,5 @@
         if (magazine)
         {
-            if (this->bStackMunition_)
+            if (deployment_ == MunitionDeployment::Stack)
                 // With stacked munition, we never have to reload
                 return false;
@@ -227,26 +252,32 @@
 
         // Check if we actually can reload
-        if (this->magazines_ == 0)
+        if (this->unassignedMagazines_ == 0)
             return false;
 
         // If we use separate magazines for each user, we definitively need a user given
-        if (this->bUseSeparateMagazines_ && !user)
+        if (deployment_ == MunitionDeployment::Separate && !user)
             return false;
 
         // If we don't use separate magazines, set user to 0
-        if (!this->bUseSeparateMagazines_)
-            user = 0;
+        if (deployment_ != MunitionDeployment::Separate)
+        {
+            user = NULL;
+        }
 
         // Remove the current magazine for the given user
-        std::map<WeaponMode*, Magazine*>::iterator it = this->currentMagazines_.find(user);
-        if (it != this->currentMagazines_.end())
-        {
+        std::map<WeaponMode*, Magazine*>::iterator it = this->assignedMagazines_.find(user);
+        if (it != this->assignedMagazines_.end())
+        {
+            if (it->first == lastFilledWeaponMode_)
+            {
+                lastFilledWeaponMode_ = NULL;
+            }            
             delete it->second;
-            this->currentMagazines_.erase(it);
+            this->assignedMagazines_.erase(it);
         }
 
         // Load a new magazine
-        this->currentMagazines_[user] = new Magazine(this, bUseReloadTime);
-        this->magazines_--;
+        this->assignedMagazines_[user] = new Magazine(this, bUseReloadTime);
+        this->unassignedMagazines_--;
 
         return true;
@@ -260,5 +291,5 @@
             return false;
 
-        if (this->bStackMunition_)
+        if (deployment_ == MunitionDeployment::Stack)
         {
             // If we stack munition, we can always add munition until we reach the limit
@@ -268,5 +299,5 @@
         {
             // Return true if any of the current magazines is not full (loading counts as full although it returns 0 munition)
-            for (std::map<WeaponMode*, Magazine*>::const_iterator it = this->currentMagazines_.begin(); it != this->currentMagazines_.end(); ++it)
+            for (std::map<WeaponMode*, Magazine*>::const_iterator it = this->assignedMagazines_.begin(); it != this->assignedMagazines_.end(); ++it)
                 if (it->second->munition_ < this->maxMunitionPerMagazine_ && it->second->bLoaded_)
                     return true;
@@ -281,8 +312,8 @@
             return false;
 
-        if (this->bStackMunition_)
+        if (deployment_ == MunitionDeployment::Stack)
         {
             // Stacking munition means, if a magazine gets full, the munition adds to a new magazine
-            Magazine* magazine = this->getMagazine(0);
+            Magazine* magazine = this->getMagazine(NULL);
             if (magazine)
             {
@@ -294,11 +325,11 @@
                 {
                     magazine->munition_ -= this->maxMunitionPerMagazine_;
-                    this->magazines_++;
+                    this->unassignedMagazines_++;
                 }
 
-                // If we reached the limit, reduze both magazines and munition to the maximum
-                if (this->magazines_ >= this->maxMagazines_)
-                {
-                    this->magazines_ = this->maxMagazines_ - 1;
+                // If we reached the limit, reduce both magazines and munition to the maximum
+                if (this->unassignedMagazines_ >= this->maxMagazines_)
+                {
+                    this->unassignedMagazines_ = this->maxMagazines_;
                     magazine->munition_ = this->maxMunitionPerMagazine_;
                 }
@@ -312,9 +343,24 @@
         else
         {
+            std::map<WeaponMode*, Magazine*>::iterator it;
+
+            // If the pointer to the weapon mode whose magazine got munition added to is NULL, then set the iterator to the beginning of the map
+            // Otherwise set it to the next weapon mode
+            if (lastFilledWeaponMode_ == NULL)
+            {
+                it = this->assignedMagazines_.begin();
+            }
+            else
+            {
+                it = this->assignedMagazines_.find(lastFilledWeaponMode_);
+                ++ it;
+            }
+
             // Share the munition equally to the current magazines
+            bool firstLoop = true;
             while (amount > 0)
             {
                 bool change = false;
-                for (std::map<WeaponMode*, Magazine*>::iterator it = this->currentMagazines_.begin(); it != this->currentMagazines_.end(); ++it)
+                while (it != this->assignedMagazines_.end())
                 {
                     // Add munition if the magazine isn't full (but only to loaded magazines)
@@ -323,11 +369,20 @@
                         it->second->munition_++;
                         amount--;
+                        lastFilledWeaponMode_ = it->first;
                         change = true;
                     }
+
+                    ++it;
                 }
 
                 // If there was no change in a loop, all magazines are full (or locked due to loading)
-                if (!change)
+                // Because the first loop does not start at the beginning of the map we have to treat is separately
+                if (!change && !firstLoop)
+                {
                     break;
+                }                    
+
+                it = this->assignedMagazines_.begin();
+                firstLoop = false;
             }
 
@@ -340,34 +395,38 @@
         // TODO: 'amount' is not used
 
-        if (this->bStackMunition_)
+        if (deployment_ == MunitionDeployment::Stack)
             // If we stack munition, we can always add new magazines because they contribute directly to the munition
             return (this->getNumMunition(0) < this->getMaxMunition());
         else
             // If we don't stack munition, we're more limited
-            return ((this->currentMagazines_.size() + this->magazines_) < this->maxMagazines_);
-    }
-
-    bool Munition::addMagazines(unsigned int amount)
-    {
+            return ((this->assignedMagazines_.size() + this->unassignedMagazines_) < this->maxMagazines_);
+    }
+
+    unsigned int Munition::addMagazines(unsigned int amount)
+    {
+        unsigned int addedMagazines = 0;
+
         if (!this->canAddMagazines(amount))
-            return false;
+            return 0;
 
         // Calculate how many magazines are needed
-        int needed_magazines = this->maxMagazines_ - this->magazines_ - this->currentMagazines_.size();
+        int needed_magazines = this->maxMagazines_ - this->unassignedMagazines_ - this->assignedMagazines_.size();
 
         // If zero or less magazines are needed, we definitively don't need more magazines (unless we stack munition - then a magazine contributes directly to the munition)
-        if (needed_magazines <= 0 && !this->bStackMunition_)
-            return false;
+        if (needed_magazines <= 0 && deployment_ != MunitionDeployment::Stack)
+            return 0;
 
         if (amount <= static_cast<unsigned int>(needed_magazines))
         {
             // We need more magazines than we get, so just add them
-            this->magazines_ += amount;
+            this->unassignedMagazines_ += amount;
+            addedMagazines = amount;
         }
         else
         {
             // We get more magazines than we need, so just add the needed amount
-            this->magazines_ += needed_magazines;
-            if (this->bStackMunition_)
+            this->unassignedMagazines_ += needed_magazines;
+            addedMagazines = needed_magazines;
+            if (deployment_ == MunitionDeployment::Stack)
             {
                 // We stack munition, so the additional amount contributes directly to the munition of the current magazine
@@ -378,17 +437,31 @@
         }
 
-        return true;
+        // Reload as many empty magazines as possible
+        // Double loop and break is needed because the reload function changes the assigned magazines. This may confuse the iterator.
+        for (unsigned int i = 0; i < addedMagazines; ++i)
+        {
+            for (std::map<WeaponMode*, Magazine*>::iterator it = this->assignedMagazines_.begin(); it != this->assignedMagazines_.end(); ++it)
+            {
+                if (needReload(it->first))
+                {
+                    reload(it->first);
+                    break;
+                }
+            }
+        }
+
+        return addedMagazines;
     }
 
     bool Munition::canRemoveMagazines(unsigned int amount) const
     {
-        if (this->bStackMunition_)
-        {
-            if (this->magazines_ >= amount)
+        if (deployment_ == MunitionDeployment::Stack)
+        {
+            if (this->unassignedMagazines_ >= amount)
             {
                 // We have enough magazines
                 return true;
             }
-            else if (this->magazines_ == amount - 1)
+            else if (this->unassignedMagazines_ == amount - 1)
             {
                 // We lack one magazine, check if the current magazine is still full, if yes we're fine
@@ -406,5 +479,5 @@
         {
             // In case we're not stacking munition, just check the number of magazines
-            return (this->magazines_ >= amount);
+            return (this->unassignedMagazines_ >= amount);
         }
 
@@ -417,13 +490,13 @@
             return false;
 
-        if (this->magazines_ >= amount)
+        if (this->unassignedMagazines_ >= amount)
         {
             // We have enough magazines, just remove the amount
-            this->magazines_ -= amount;
-        }
-        else if (this->bStackMunition_)
+            this->unassignedMagazines_ -= amount;
+        }
+        else if (deployment_ == MunitionDeployment::Stack)
         {
             // We don't have enough magazines, but we're stacking munition, so additionally remove the bullets from the current magazine
-            this->magazines_ = 0;
+            this->unassignedMagazines_ = 0;
             Magazine* magazine = this->getMagazine(0);
             if (magazine)
@@ -437,17 +510,21 @@
     {
         // If we use separate magazines, we need a user
-        if (this->bUseSeparateMagazines_ && !user)
+        if (deployment_ == MunitionDeployment::Separate && !user)
             return false;
 
         // If we don't use separate magazines, set user to 0
-        if (!this->bUseSeparateMagazines_)
-            user = 0;
+        if (deployment_ != MunitionDeployment::Separate)
+            user = NULL;
 
         // Remove the current magazine for the given user
-        std::map<WeaponMode*, Magazine*>::iterator it = this->currentMagazines_.find(user);
-        if (it != this->currentMagazines_.end())
-        {
+        std::map<WeaponMode*, Magazine*>::iterator it = this->assignedMagazines_.find(user);
+        if (it != this->assignedMagazines_.end())
+        {
+            if (it->first == lastFilledWeaponMode_)
+            {
+                lastFilledWeaponMode_ = NULL;
+            }
             delete it->second;
-            this->currentMagazines_.erase(it);
+            this->assignedMagazines_.erase(it);           
             return true;
         }
@@ -465,5 +542,5 @@
         this->bLoaded_ = false;
 
-        if (bUseReloadTime && munition->reloadTime_ > 0 && !munition->bStackMunition_)
+        if (bUseReloadTime && munition->reloadTime_ > 0 && !munition->deployment_ == MunitionDeployment::Stack)
         {
             const ExecutorPtr& executor = createExecutor(createFunctor(&Magazine::loaded, this));
Index: code/branches/presentationHS15/src/orxonox/weaponsystem/Munition.h
===================================================================
--- code/branches/presentationHS15/src/orxonox/weaponsystem/Munition.h	(revision 10959)
+++ code/branches/presentationHS15/src/orxonox/weaponsystem/Munition.h	(revision 10961)
@@ -24,5 +24,5 @@
  *      Fabian 'x3n' Landau
  *   Co-authors:
- *      ...
+ *      Fabien Vultier
  *
  */
@@ -39,6 +39,16 @@
 namespace orxonox
 {
+    namespace MunitionDeployment
+    {
+        enum Value
+        {
+            Separate, // Every comsuming weapon mode has its own magazine. It is possible that one weapon mode is out of ammo while another still has some.
+            Share, // All comsuming weapon modes take their munition from the same magazine. If this magazine is empty a new one is loaded.
+            Stack // There is only one magazine where all the munition is stored. Use this deployment mode for heavy weapons loke rockets, bombs, ...
+        };
+    }
+
     class _OrxonoxExport Munition : public BaseObject
-    {
+    {        
         struct Magazine
         {
@@ -59,4 +69,6 @@
             virtual ~Munition();
 
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode);
+
             unsigned int getNumMunition(WeaponMode* user) const;
             unsigned int getNumMunitionInCurrentMagazine(WeaponMode* user) const;
@@ -68,4 +80,7 @@
             inline unsigned int getMaxMunitionPerMagazine() const
                 { return this->maxMunitionPerMagazine_; }
+            inline MunitionDeployment::Value getMunitionDeployment() const
+                { return deployment_; }
+
 
             bool canTakeMunition(unsigned int amount, WeaponMode* user) const;
@@ -82,5 +97,10 @@
 
             bool canAddMagazines(unsigned int amount) const;
-            bool addMagazines(unsigned int amount);
+            /**
+            @brief Try to add magazines.
+            @param amount The amount of magazines tried to add.
+            @return The amount of magazines sucessfully added.
+            */
+            unsigned int addMagazines(unsigned int amount);
 
             bool canRemoveMagazines(unsigned int amount) const;
@@ -92,16 +112,22 @@
             unsigned int maxMunitionPerMagazine_;
             unsigned int maxMagazines_;
-            unsigned int magazines_;
-            std::map<WeaponMode*, Magazine*> currentMagazines_;
+            unsigned int unassignedMagazines_; // Number of magazines that are not assigned to a weapon mode. These are alway treated as full.
+            std::map<WeaponMode*, Magazine*> assignedMagazines_; // Maps weapon modes to magazines that are currently used.
 
-            bool bUseSeparateMagazines_;
-            bool bStackMunition_;
+            MunitionDeployment::Value deployment_; // Defines the behaviour how munition and magazines are distributed to the consuming weapon modes.
+
             bool bAllowMunitionRefilling_;
             bool bAllowMultiMunitionRemovementUnderflow_;
 
-            float reloadTime_;
+            float reloadTime_; // The time needed to replace a magazine by a new one.
+            WeaponMode* lastFilledWeaponMode_; // Pointer to the weapon mode that got the last munition during the last call of addMunition.
 
         private:
             Magazine* getMagazine(WeaponMode* user) const;
+            inline void setMaxMagazines(unsigned int maxMagazines)
+                { this->maxMagazines_ = maxMagazines; }
+            inline void setMaxMunitionPerMagazine(unsigned int maxMunitionPerMagazine)
+                { this->maxMunitionPerMagazine_ = maxMunitionPerMagazine; }
+            void setNumMagazines(unsigned int numMagazines);
     };
 }
Index: code/branches/presentationHS15/src/orxonox/weaponsystem/ReplenishingMunition.cc
===================================================================
--- code/branches/presentationHS15/src/orxonox/weaponsystem/ReplenishingMunition.cc	(revision 10961)
+++ code/branches/presentationHS15/src/orxonox/weaponsystem/ReplenishingMunition.cc	(revision 10961)
@@ -0,0 +1,92 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file ReplenishingMunition.h
+    @brief Implementation of the ReplenishingMunition class.
+*/
+
+#include "ReplenishingMunition.h"
+
+#include "core/CoreIncludes.h"
+#include "core/command/Executor.h"
+#include "core/XMLPort.h"
+
+namespace orxonox
+{
+    RegisterClass(ReplenishingMunition);
+
+    ReplenishingMunition::ReplenishingMunition(Context* context) : Munition(context)
+    {
+        RegisterObject(ReplenishingMunition);
+
+        this->replenishInterval_ = 1.0f;
+        this->replenishAmount_ = 1;
+
+        // Use the timer to initialize itself after the first tick (because the real values for
+        // replenishIntervall_ and replenishMunitionAmount_ will be set in the constructor of the
+        // inheriting class, which comes after this constructor)
+        this->replenishingTimer_.setTimer(0.0f, false, createExecutor(createFunctor(&ReplenishingMunition::initializeTimer, this)));
+    }
+
+    void ReplenishingMunition::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(ReplenishingMunition, XMLPort, xmlelement, mode);
+
+        XMLPortParam(ReplenishingMunition, "replenishamount", setReplenishAmount, getReplenishAmount, xmlelement, mode);
+        XMLPortParam(ReplenishingMunition, "replenishinterval", setReplenishInterval, getReplenishInterval, xmlelement, mode);
+    }    
+
+    float ReplenishingMunition::getProgress()
+    {
+        return replenishingTimer_.getRemainingTime()/this->replenishInterval_;
+    }
+
+    void ReplenishingMunition::initializeTimer()
+    {
+        // Initialize the timer
+        this->replenishingTimer_.setTimer(this->replenishInterval_, true, createExecutor(createFunctor(&ReplenishingMunition::replenish, this)));
+    }
+
+    void ReplenishingMunition::replenish()
+    {
+        if (this->canAddMagazines(this->replenishAmount_))
+        {
+            // Make a temporary copy of bAllowMunitionRefilling_, because this might be disallowed in every
+            // case except the internal munition replenishing
+            bool temp = this->bAllowMunitionRefilling_;
+            this->bAllowMunitionRefilling_ = true;
+
+            // Replenish munition
+            this->addMagazines(this->replenishAmount_);
+
+            // Write back the temporary value
+            this->bAllowMunitionRefilling_ = temp;            
+        }
+    }
+}
Index: code/branches/presentationHS15/src/orxonox/weaponsystem/ReplenishingMunition.h
===================================================================
--- code/branches/presentationHS15/src/orxonox/weaponsystem/ReplenishingMunition.h	(revision 10961)
+++ code/branches/presentationHS15/src/orxonox/weaponsystem/ReplenishingMunition.h	(revision 10961)
@@ -0,0 +1,81 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation; either version 2
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file ReplenishingMunition.h
+    @brief Definition of the ReplenishingMunition class.
+*/
+
+#ifndef _ReplenishingMunition_H__
+#define _ReplenishingMunition_H__
+
+#include "tools/Timer.h"
+#include "Munition.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        Munition that is replenished by a certain amount each time interval.
+    @author
+        Fabian 'x3n' Landau
+    @ingroup WeaponsMunitions
+    */
+    class _OrxonoxExport ReplenishingMunition : public Munition
+    {
+        public:
+            ReplenishingMunition(Context* context);
+            virtual ~ReplenishingMunition() {}
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode);
+            
+            virtual float getProgress();
+            inline float getReplenishAmount() const
+                { return replenishAmount_; }
+            inline float getReplenishInterval() const
+                { return replenishInterval_; }
+
+        protected:                          
+            float replenishInterval_; //!< The interval in which the munition is replenished.
+            unsigned int replenishAmount_; //!< The amount of magazines by which it is replenished.
+
+        private:
+            void replenish(); //!< Every call of this function replenishes the munition. This function is called by the timer.
+            void initializeTimer();
+
+            Timer replenishingTimer_; //!< Timer to do the replenishing.
+
+            inline void setReplenishAmount(unsigned int replenishAmount)
+                { this->replenishAmount_ = replenishAmount; }
+            inline void setReplenishInterval(float replenishInterval)
+                { this->replenishInterval_ = replenishInterval; }              
+    };
+}
+
+#endif /* _ReplenishingMunition_H__ */
Index: code/branches/presentationHS15/src/orxonox/weaponsystem/Weapon.cc
===================================================================
--- code/branches/presentationHS15/src/orxonox/weaponsystem/Weapon.cc	(revision 10959)
+++ code/branches/presentationHS15/src/orxonox/weaponsystem/Weapon.cc	(revision 10961)
@@ -134,4 +134,8 @@
     }
 
+    /**
+    @brief
+        Reload all @ref orxonox::WeaponMode weapon modes of this weapon.
+    */
     void Weapon::reload()
     {
@@ -151,3 +155,9 @@
             it->second->setWeapon(this);
     }
+
+    void Weapon::updateMunition()
+    {
+        for (std::multimap<unsigned int, WeaponMode*>::iterator it = this->weaponmodes_.begin(); it != this->weaponmodes_.end(); ++it)
+            it->second->updateMunition();
+    }
 }
Index: code/branches/presentationHS15/src/orxonox/weaponsystem/Weapon.h
===================================================================
--- code/branches/presentationHS15/src/orxonox/weaponsystem/Weapon.h	(revision 10959)
+++ code/branches/presentationHS15/src/orxonox/weaponsystem/Weapon.h	(revision 10961)
@@ -57,4 +57,8 @@
             void addWeaponmode(WeaponMode* weaponmode);
             WeaponMode* getWeaponmode(unsigned int index) const;
+            inline std::multimap<unsigned int, WeaponMode*>* getAllWeaponmodes()
+                { return &weaponmodes_; }
+            inline int getNumWeaponModes() const
+                { return weaponmodes_.size(); }
 
             /**
@@ -75,4 +79,5 @@
             inline WeaponSlot * getWeaponSlot() const
                 { return this->weaponSlot_; }
+            void updateMunition();
 
         private:
Index: code/branches/presentationHS15/src/orxonox/weaponsystem/WeaponMode.cc
===================================================================
--- code/branches/presentationHS15/src/orxonox/weaponsystem/WeaponMode.cc	(revision 10959)
+++ code/branches/presentationHS15/src/orxonox/weaponsystem/WeaponMode.cc	(revision 10961)
@@ -75,4 +75,6 @@
         this->muzzleOrientation_ = Quaternion::IDENTITY;
 
+        hudImageString_ = "WSHUD_WM_Unknown";
+
         if( GameMode::isMaster() )
         {
@@ -125,5 +127,6 @@
             this->bSoundAttached_ = true;
         }
-
+        
+        // Fireing is only possible if this weapon mode is not reloading and there is enough munition
         if (!this->bReloading_ && this->munition_ && this->munition_->takeMunition(this->munitionPerShot_, this))
         {
@@ -134,11 +137,19 @@
                 if (this->munition_->reload(this))
                 {
+                    // If true, the weapon reloads in parallel to the magazine reloading
                     if (this->bParallelReload_)
+                    {
+                        // The time needed to reload is the maximum of the reload time of the weapon mode and the magazine.
                         tempReloadtime = std::max(this->reloadTime_, this->munition_->getReloadTime());
+                    }                        
                     else
+                    {
+                        // The time needed to reload is the sum of the reload time of the weapon mode and the magazine.
                         tempReloadtime = this->reloadTime_ + this->munition_->getReloadTime();
+                    }                        
                 }
             }
 
+            // Mark this weapon mode as reloading and start the reload timer
             this->bReloading_ = true;
             this->reloadTimer_.setInterval(tempReloadtime);
@@ -232,5 +243,7 @@
         }
         else
-            this->munition_ = 0;
+        {
+            this->munition_ = NULL;
+        }
     }
 
@@ -283,6 +296,8 @@
     }
 
-    void WeaponMode::setDefaultSoundWithVolume(const std::string& soundPath, const float soundVolume){
-        if (this->defSndWpnFire_) {
+    void WeaponMode::setDefaultSoundWithVolume(const std::string& soundPath, const float soundVolume)
+    {
+        if (this->defSndWpnFire_)
+        {
             this->defSndWpnFire_->setSource(soundPath);
             this->defSndWpnFire_->setVolume(soundVolume);
Index: code/branches/presentationHS15/src/orxonox/weaponsystem/WeaponMode.h
===================================================================
--- code/branches/presentationHS15/src/orxonox/weaponsystem/WeaponMode.h	(revision 10959)
+++ code/branches/presentationHS15/src/orxonox/weaponsystem/WeaponMode.h	(revision 10961)
@@ -38,4 +38,5 @@
 #include "core/class/SubclassIdentifier.h"
 #include "tools/Timer.h"
+#include "Munition.h"
 
 namespace orxonox
@@ -104,4 +105,6 @@
             inline bool getParallelReload() const
                 { return this->bParallelReload_; }
+            inline bool getReloading() const
+                { return this->bReloading_; }
 
 
@@ -147,4 +150,8 @@
             Vector3 getTarget();
 
+            inline const std::string& getHUDImageString() const
+                { return this->hudImageString_; }            
+
+            void updateMunition();
         protected:
             virtual void fire() = 0;
@@ -155,6 +162,6 @@
 
             float reloadTime_;
-            bool bAutoReload_;
-            bool bParallelReload_;
+            bool bAutoReload_; // If true, the weapon reloads the magazine automatically.
+            bool bParallelReload_; // If true, the weapon reloads in parallel to the magazine reloading.
 
             float damage_;
@@ -163,6 +170,7 @@
             Vector3 muzzleOffset_;
 
-        private:
-            void updateMunition();
+            std::string hudImageString_;
+
+        private:            
             void reloaded();
 
@@ -175,5 +183,5 @@
 
             Timer reloadTimer_;
-            bool bReloading_;
+            bool bReloading_; // If true, this weapon mode is marked as reloading.
 
             Vector3 muzzlePosition_;
@@ -181,5 +189,5 @@
 
             WorldSound* defSndWpnFire_;
-            bool        bSoundAttached_;
+            bool bSoundAttached_;
     };
 }
Index: code/branches/presentationHS15/src/orxonox/weaponsystem/WeaponPack.cc
===================================================================
--- code/branches/presentationHS15/src/orxonox/weaponsystem/WeaponPack.cc	(revision 10959)
+++ code/branches/presentationHS15/src/orxonox/weaponsystem/WeaponPack.cc	(revision 10961)
@@ -124,4 +124,9 @@
     }
 
+    std::vector<Weapon*>* WeaponPack::getAllWeapons()
+    {
+        return &weapons_;        
+    }    
+
     void WeaponPack::addDefaultWeaponmodeLink(DefaultWeaponmodeLink* link)
     {
@@ -156,3 +161,9 @@
             (*it)->setWeaponPack(this);
     }
+
+    void WeaponPack::updateMunition()
+    {
+        for (std::vector<Weapon *>::const_iterator it = this->weapons_.begin(); it != this->weapons_.end(); ++it)
+            (*it)->updateMunition();
+    }
 }
Index: code/branches/presentationHS15/src/orxonox/weaponsystem/WeaponPack.h
===================================================================
--- code/branches/presentationHS15/src/orxonox/weaponsystem/WeaponPack.h	(revision 10959)
+++ code/branches/presentationHS15/src/orxonox/weaponsystem/WeaponPack.h	(revision 10961)
@@ -52,4 +52,5 @@
             void removeWeapon(Weapon * weapon);
             Weapon * getWeapon(unsigned int index) const;
+            std::vector<Weapon*>* getAllWeapons();
 
             inline size_t getNumWeapons() const
@@ -65,4 +66,5 @@
             inline WeaponSystem * getWeaponSystem() const
                 { return this->weaponSystem_; }
+            void updateMunition();
 
         private:
Index: code/branches/presentationHS15/src/orxonox/weaponsystem/WeaponSystem.cc
===================================================================
--- code/branches/presentationHS15/src/orxonox/weaponsystem/WeaponSystem.cc	(revision 10959)
+++ code/branches/presentationHS15/src/orxonox/weaponsystem/WeaponSystem.cc	(revision 10961)
@@ -240,4 +240,9 @@
     }
 
+    std::vector<WeaponPack *> * WeaponSystem::getAllWeaponPacks()
+    {
+        return &weaponPacks_;
+    }    
+
     bool WeaponSystem::swapWeaponSlots(WeaponSlot * wSlot1, WeaponSlot * wSlot2)
     {
@@ -310,13 +315,35 @@
             return it->second;
         }
-        else if (identifier->getIdentifier()->isA(Class(Munition)))
-        {
-            Munition* munition = identifier->fabricate(this->getContext());
-            this->munitions_[identifier->getIdentifier()] = munition;
-            return munition;
-        }
         else
         {
-            return 0;
+            return NULL;
+        }
+    }
+
+    void WeaponSystem::addMunition(Munition* munition)
+    {
+        if (munition == NULL)
+        {
+            return;
+        }
+
+        SubclassIdentifier<Munition> identifier = munition->getIdentifier();
+
+        if (identifier)
+        {
+            this->munitions_[identifier] = munition;
+            updateMunition();
+        }
+        else
+        {
+            orxout(internal_warning) << "Adding munition failed. identifier == NULL " << endl;
+        }
+    }
+
+    void WeaponSystem::updateMunition()
+    {
+        for (std::vector<WeaponPack*>::iterator it = this->weaponPacks_.begin(); it != this->weaponPacks_.end(); ++it)
+        {
+            (*it)->updateMunition();
         }
     }
Index: code/branches/presentationHS15/src/orxonox/weaponsystem/WeaponSystem.h
===================================================================
--- code/branches/presentationHS15/src/orxonox/weaponsystem/WeaponSystem.h	(revision 10959)
+++ code/branches/presentationHS15/src/orxonox/weaponsystem/WeaponSystem.h	(revision 10961)
@@ -67,4 +67,5 @@
             void removeWeaponPack(WeaponPack * wPack);
             WeaponPack * getWeaponPack(unsigned int index) const;
+            std::vector<WeaponPack *> * getAllWeaponPacks();
 
             // configure slots and firemodes
@@ -76,4 +77,5 @@
 
             Munition * getMunition(SubclassIdentifier<Munition> * identifier);
+            void addMunition(Munition* munition);
 
             inline void setPawn(Pawn * pawn)
@@ -95,4 +97,6 @@
 
         private:
+            void updateMunition();
+            
             std::map<unsigned int, WeaponSet *> weaponSets_;
             std::vector<WeaponSlot *> weaponSlots_;
