Index: code/trunk/src/orxonox/worldentities/pawns/CMakeLists.txt
===================================================================
--- code/trunk/src/orxonox/worldentities/pawns/CMakeLists.txt	(revision 9950)
+++ code/trunk/src/orxonox/worldentities/pawns/CMakeLists.txt	(revision 10216)
@@ -4,4 +4,5 @@
   Pawn.cc
   SpaceShip.cc
+  ModularSpaceShip.cc
   TeamBaseMatchBase.cc
   Destroyer.cc
Index: code/trunk/src/orxonox/worldentities/pawns/ModularSpaceShip.cc
===================================================================
--- code/trunk/src/orxonox/worldentities/pawns/ModularSpaceShip.cc	(revision 10216)
+++ code/trunk/src/orxonox/worldentities/pawns/ModularSpaceShip.cc	(revision 10216)
@@ -0,0 +1,308 @@
+/*
+ *   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:
+ *      Noe Pedrazzini
+ *
+ */
+
+#include "ModularSpaceShip.h"
+
+#include <BulletDynamics/Dynamics/btRigidBody.h>
+
+#include "core/CoreIncludes.h"
+#include "core/config/ConfigValueIncludes.h"
+#include "core/Template.h"
+#include "core/XMLPort.h"
+#include "util/Math.h"
+#include "gametypes/Gametype.h"
+#include "core/command/ConsoleCommand.h"
+
+#include "items/ShipPart.h"
+#include "items/Engine.h"
+#include "worldentities/StaticEntity.h"
+#include <BulletCollision/CollisionShapes/btCollisionShape.h>
+#include <BulletCollision/CollisionShapes/btCompoundShape.h>
+
+
+
+namespace orxonox
+{
+    SetConsoleCommand("ModularSpaceShip", "killshippart", &ModularSpaceShip::killShipPartStatic);
+
+    RegisterClass(ModularSpaceShip);
+
+    std::map<StaticEntity*, ShipPart*>* ModularSpaceShip::partMap_s = 0;
+
+    ModularSpaceShip::ModularSpaceShip(Context* context) : SpaceShip(context)
+    {
+        RegisterObject(ModularSpaceShip);
+
+        this->registerVariables();
+
+        ModularSpaceShip::partMap_s = &(this->partMap_);
+
+    }
+
+    ModularSpaceShip::~ModularSpaceShip()
+    {
+        if (this->isInitialized())
+        {
+
+        }
+    }
+
+    void ModularSpaceShip::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(ModularSpaceShip, XMLPort, xmlelement, mode);
+        XMLPortObject(ModularSpaceShip, ShipPart, "parts", addShipPart, getShipPart, xmlelement, mode);
+    }
+
+    void ModularSpaceShip::registerVariables()
+    {
+        return;
+    }
+
+    /**
+    @brief
+        Searches for ShipParts matching to StaticEntities.
+    */
+    void ModularSpaceShip::updatePartAssignment()
+    {
+        // iterate through all attached objects
+        for (unsigned int i=0; i < this->getAttachedObjects().size(); i++)
+        {
+            if (this->getAttachedObject(i) == NULL)
+            {
+                break;
+            }
+            // iterate through all attached parts
+            for(unsigned int j = 0; j < this->partList_.size(); j++)
+            {
+                // if the name of the part matches the name of the object, add the object to that parts entitylist (unless it was already done).
+                if((this->partList_[j]->getName() == this->getAttachedObject(i)->getName()) && !this->partList_[j]->hasEntity(orxonox_cast<StaticEntity*>(this->getAttachedObject(i))))
+                {
+                    // The Entity is added to the part's entityList_
+                    this->partList_[j]->addEntity(orxonox_cast<StaticEntity*>(this->getAttachedObject(i)));
+                    // An entry in the partMap_ is created, assigning the part to the entity.
+                    this->addPartEntityAssignment((StaticEntity*)(this->getAttachedObject(i)), this->partList_[j]);
+                }
+            }
+        }
+    }
+
+    /**
+    @brief
+        Creates a new assignment for the given StaticEntity and ShipPart in the partMap_
+    @param entity
+        A pointer to the StaticEntity
+    @param part
+        A pointer to the ShipPart.
+    */
+    void ModularSpaceShip::addPartEntityAssignment(StaticEntity* entity, ShipPart* part)
+    {
+        if (!entity || !part)
+            return;
+
+        if (this->partMap_.find(entity) != this->partMap_.end())
+                {
+                    orxout(internal_warning) << "Assigning an Entity to multiple parts is not yet supported." << endl;
+                    return;
+                }
+
+        this->partMap_[entity] = part;
+    }
+
+
+    /**
+    @brief
+        Get the ShipPart an attached entity belongs to.
+    @param entity
+        The entity to be searched.
+    @return
+        Returns a pointer to the ShipPart the entity belongs to.
+    */
+    ShipPart* ModularSpaceShip::getPartOfEntity(StaticEntity* entity) const
+    {
+        for (std::map<StaticEntity*, ShipPart*>::const_iterator it = this->partMap_.begin(); it != this->partMap_.end(); ++it)
+        {
+            if (it->first == entity)
+                return it->second;
+        }
+        return NULL;
+    }
+
+    /**
+    @brief
+        If the damage occurred on an attached StaticEntity, the damage is given to the corresponding ShipPart to handle.
+    */
+    void ModularSpaceShip::damage(float damage, float healthdamage, float shielddamage, Pawn* originator, const btCollisionShape* cs)
+    {
+        if (this->getPartOfEntity((StaticEntity*)(cs->getUserPointer())) != NULL)
+            this->getPartOfEntity((StaticEntity*)(cs->getUserPointer()))->handleHit(damage, healthdamage, shielddamage, originator);
+        else
+            SpaceShip::damage(damage, healthdamage, shielddamage, originator, cs);
+    }
+
+    /**
+    @brief
+        STATIC: Needed for consolecommand. Kills the ShipPart with the given name. Used from the console-command "ModularSpaceShip killshippart [string]".
+    @param name
+        The name of the part to be killed.
+    */
+    void ModularSpaceShip::killShipPartStatic(std::string name)
+    {
+        for (std::map<StaticEntity*, ShipPart*>::const_iterator it = ModularSpaceShip::partMap_s->begin(); it != ModularSpaceShip::partMap_s->end(); ++it)
+        {
+            if (it->second->getName() == name)
+            {
+                it->second->setAlive(false);
+                return;
+            }
+        }
+        orxout(internal_warning) << "Could not apply damage to ShipPart \"" << name << "\". Part not found." << endl;
+    }
+
+    /**
+    @brief
+        Kills the ShipPart with the given name. Used from the console-command "ModularSpaceShip killshippart [string]".
+    @param name
+        The name of the part to be killed.
+    */
+    void ModularSpaceShip::killShipPart(std::string name)
+    {
+        for (std::map<StaticEntity*, ShipPart*>::const_iterator it = ModularSpaceShip::partMap_.begin(); it != ModularSpaceShip::partMap_.end(); ++it)
+        {
+            if (it->second->getName() == name)
+            {
+                it->second->setAlive(false);
+                return;
+            }
+        }
+        orxout(internal_warning) << "Could not apply damage to ShipPart \"" << name << "\". Part not found." << endl;
+    }
+
+    /**
+    @brief
+        Add a ShipPart to the SpaceShip.
+    @param engine
+        A pointer to the ShipPart to be added.
+    */
+    void ModularSpaceShip::addShipPart(ShipPart* part)
+    {
+        OrxAssert(part != NULL, "The ShipPart cannot be NULL.");
+        this->partList_.push_back(part);
+        part->setParent(this);
+        this->updatePartAssignment();
+    }
+
+    /**
+    @brief
+        Get the i-th ShipPart of the SpaceShip.
+    @return
+        Returns a pointer to the i-the ShipPart. NULL if there is no ShipPart with that index.
+    */
+    ShipPart* ModularSpaceShip::getShipPart(unsigned int index)
+    {
+        if(this->partList_.size() <= index)
+            return NULL;
+        else
+            return this->partList_[index];
+    }
+
+    /**
+    @brief
+        Looks for an attached ShipPart with a certain name.
+    @param name
+        The name of the ShipPart to be returned.
+    @return
+        Pointer to the ShipPart with the given name, or NULL if not found.
+    */
+    ShipPart* ModularSpaceShip::getShipPartByName(std::string name)
+    {
+        for(std::vector<ShipPart*>::iterator it = this->partList_.begin(); it != this->partList_.end(); ++it)
+        {
+            if(orxonox_cast<ShipPart*>(*it)->getName() == name)
+            {
+                return orxonox_cast<ShipPart*>(*it);
+            }
+        }
+        orxout(internal_warning) << "Couldn't find ShipPart with name \"" << name << "\"." << endl;
+        return NULL;
+    }
+
+    /**
+    @brief
+        Check whether the SpaceShip has a particular Engine.
+    @param engine
+        A pointer to the Engine to be checked.
+    */
+    bool ModularSpaceShip::hasShipPart(ShipPart* part) const
+    {
+        for(unsigned int i = 0; i < this->partList_.size(); i++)
+        {
+            if(this->partList_[i] == part)
+                return true;
+        }
+        return false;
+    }
+
+
+    /**
+    @brief
+        Removes a ShipPart from the SpaceShip, destroying the corresponding StaticEntity
+    @param part
+        The ShipPart to be removed.
+    */
+    void ModularSpaceShip::removeShipPart(ShipPart* part)
+    {
+        // Remove the part from the partList_
+        std::vector<ShipPart*>::iterator it = this->partList_.begin();
+        for(unsigned int i = 0; i < this->partList_.size(); i++)
+        {
+            if(this->partList_[i] == part)
+            {
+                this->partList_.erase(it);
+                break;
+            }
+            it++;
+        }
+        // Remove the part-entity assignment and detach the Entity of this ShipPart
+        for (std::map<StaticEntity*, ShipPart*>::iterator itt = this->partMap_.begin(); itt != this->partMap_.end(); )
+        {
+            if (itt->second == part)
+            {
+                this->detach(itt->first);
+                itt->first->destroy();
+                //itt->first->setActive(false);
+                //itt->first->setVisible(false);
+                //itt->first->setCollisionResponse(false);
+                //itt->first->setCollisionType(None);
+                //itt->first->deactivatePhysics();
+                this->partMap_.erase(itt++);
+            } else {
+                ++itt;
+            }
+        }
+    }
+}
Index: code/trunk/src/orxonox/worldentities/pawns/ModularSpaceShip.h
===================================================================
--- code/trunk/src/orxonox/worldentities/pawns/ModularSpaceShip.h	(revision 10216)
+++ code/trunk/src/orxonox/worldentities/pawns/ModularSpaceShip.h	(revision 10216)
@@ -0,0 +1,141 @@
+/*
+ *   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:
+ *      Noe Pedrazzini
+ *
+ */
+
+#ifndef _ModularSpaceShip_H__
+#define _ModularSpaceShip_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <string>
+#include <LinearMath/btVector3.h>
+
+#include "tools/Timer.h"
+#include "util/Math.h"
+#include "util/OrxAssert.h"
+
+#include "SpaceShip.h"
+#include "items/ShipPart.h"
+#include <map>
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        The SpaceShip is the principal entity through which the player interacts with the game. Its main function is to fly, however many things, such as @ref orxonox::Engine Engines or @ref orxonox::Weapon Weapons, can be attached to it.
+        The ModularSpaceShip is an extension of a @ref orxonox::SpaceShip SpaceShip, which uses @ref orxonox::ShipPart ShipParts to allow entities attached to it to be destroyed individually.
+
+        There are several parameters that define the behavior of the ModularSpaceShip>
+        - The <b>rotationThrust</b>, specifies the force with which the ModularSpaceShip rotates.
+        - The <b>boost</b>, there are quite some parameters pertaining to boosting. The boost is a special move of the ModularSpaceShip, where, for a limited amount of time, it can fly considerably faster than usual. The <b>boostPower</b> is the amount of power available for boosting. The <b>boostPowerRate</b> is the rate at which the boost power is replenished. The <b>boostRate</b> is the rate at which boosting uses power. And the <b>boostCooldownDuration</b> is the time the ModularSpaceShip cannot boost, once all the boost power has been used up. Naturally all of these parameters must be non-negative.
+        - The <b>boost shaking</b>, when the ModularSpaceShip boosts, the camera shakes to create a more immersive effect. Two parameters can be used to adjust the effect. The <b>shakeFrequency</b> is the frequency with which the camera shakes. And the <b>shakeAmplitude</b> is the amount with which the camera shakes. Again these parameters must bee non-negative.
+        - The <b>lift</b> creates a more natural flight feeling through the addition of a lift force. There are again tow parameters that can be specified. The <b>lift</b> which is the lift force that is applied. And the <b>stallSpeed</b> which is the forward speed after which no more lift is generated.
+
+        As mentioned @ref orxonox::Engine Engines can be mounted on the ModularSpaceShip.
+        In order to assign attached entities to a ShipPart, a ShipPart with the same name as the corresponding entity needs to be created in the <parts> tag.
+        Here is a (primitive) example of a ModularSpaceShip defined in XML:
+        @code
+        <ModularSpaceShip
+            rotationThrust    = 50
+
+            lift = 1;
+            stallSpeed = 220;
+
+            boostPower            = 15
+            boostPowerRate        = 1
+            boostRate             = 5
+            boostCooldownDuration = 10
+
+            shakeFrequency = 15
+            shakeAmplitude = 9
+
+            collisionType     = "dynamic"
+            mass              = 100
+            linearDamping     = 0.7
+            angularDamping    = 0.9999999
+            >
+                <attached>
+                    <StaticEntity name="wing"  . . .  />
+                    <StaticEntity name="tail" . . . />
+                </attached>
+                <parts>
+                    <ShipPart name="wing" . . . />
+                    <ShipPart name="tail" . . . />
+                </parts>
+                <engines>
+                    <Engine />
+                    <Engine />
+                </engines>
+            </ModularSpaceShip>
+        @endcode
+
+    @author
+        Fabian 'x3n' Landau, Noe Pedrazzini
+    */
+    class _OrxonoxExport ModularSpaceShip : public SpaceShip
+    {
+        public:
+            ModularSpaceShip(Context* context);
+            virtual ~ModularSpaceShip();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode);
+
+            void addPartEntityAssignment(StaticEntity* entity, ShipPart* part);
+            ShipPart* getPartOfEntity(StaticEntity* entity) const;
+
+            virtual void damage(float damage, float healthdamage = 0.0f, float shielddamage = 0.0f, Pawn* originator = NULL, const btCollisionShape* cs = NULL);
+
+            static void killShipPartStatic(std::string name);
+            void killShipPart(std::string name);
+
+            void addShipPart(ShipPart* part);
+            ShipPart* getShipPart(unsigned int index);
+            ShipPart* getShipPartByName(std::string name);
+            bool hasShipPart(ShipPart* part) const;
+            void removeShipPart(ShipPart* part);
+
+            inline void setRotationThrust(float val)
+                { this->rotationThrust_ = val; }
+            inline float getRotationThrust()
+                { return this->rotationThrust_; }
+
+            virtual void updatePartAssignment();
+
+        protected:
+
+
+        private:
+            void registerVariables();
+            std::vector<ShipPart*> partList_;                       // The list of all Parts mounted on this ModularSpaceShip.
+            std::map<StaticEntity*, ShipPart*> partMap_;            // Map of Part-Entity-assignments
+            static std::map<StaticEntity*, ShipPart*>* partMap_s;
+        
+    };
+}
+
+#endif /* _ModularSpaceShip_H__ */
Index: code/trunk/src/orxonox/worldentities/pawns/Pawn.cc
===================================================================
--- code/trunk/src/orxonox/worldentities/pawns/Pawn.cc	(revision 9950)
+++ code/trunk/src/orxonox/worldentities/pawns/Pawn.cc	(revision 10216)
@@ -244,5 +244,5 @@
     }
 
-    void Pawn::damage(float damage, float healthdamage, float shielddamage, Pawn* originator)
+    void Pawn::damage(float damage, float healthdamage, float shielddamage, Pawn* originator, const btCollisionShape* cs)
     {
         // Applies multiplier given by the DamageBoost Pickup.
@@ -279,19 +279,18 @@
 
 */
-    void Pawn::hit(Pawn* originator, const Vector3& force, float damage, float healthdamage, float shielddamage)
+    void Pawn::hit(Pawn* originator, const Vector3& force, const btCollisionShape* cs, float damage, float healthdamage, float shielddamage)
     {
         if (this->getGametype() && this->getGametype()->allowPawnHit(this, originator) && (!this->getController() || !this->getController()->getGodMode()) )
         {
-            this->damage(damage, healthdamage, shielddamage, originator);
+            this->damage(damage, healthdamage, shielddamage, originator, cs);
             this->setVelocity(this->getVelocity() + force);
         }
     }
 
-
-    void Pawn::hit(Pawn* originator, btManifoldPoint& contactpoint, float damage, float healthdamage, float shielddamage)
+    void Pawn::hit(Pawn* originator, btManifoldPoint& contactpoint, const btCollisionShape* cs, float damage, float healthdamage, float shielddamage)
     {
         if (this->getGametype() && this->getGametype()->allowPawnHit(this, originator) && (!this->getController() || !this->getController()->getGodMode()) )
         {
-            this->damage(damage, healthdamage, shielddamage, originator);
+            this->damage(damage, healthdamage, shielddamage, originator, cs);
 
             if ( this->getController() )
@@ -559,5 +558,3 @@
         return BLANKSTRING;
     }
-
-
 }
Index: code/trunk/src/orxonox/worldentities/pawns/Pawn.h
===================================================================
--- code/trunk/src/orxonox/worldentities/pawns/Pawn.h	(revision 9950)
+++ code/trunk/src/orxonox/worldentities/pawns/Pawn.h	(revision 10216)
@@ -126,6 +126,6 @@
             //virtual void hit(Pawn* originator, const Vector3& force, float damage);
             //virtual void hit(Pawn* originator, btManifoldPoint& contactpoint, float damage);
-            virtual void hit(Pawn* originator, const Vector3& force, float damage, float healthdamage = 0.0f, float shielddamage = 0.0f);
-            virtual void hit(Pawn* originator, btManifoldPoint& contactpoint, float damage, float healthdamage = 0.0f, float shielddamage = 0.0f);
+            virtual void hit(Pawn* originator, const Vector3& force, const btCollisionShape* cs, float damage, float healthdamage = 0.0f, float shielddamage = 0.0f);
+            virtual void hit(Pawn* originator, btManifoldPoint& contactpoint, const btCollisionShape* cs, float damage, float healthdamage = 0.0f, float shielddamage = 0.0f);
 
             virtual void kill();
@@ -196,5 +196,5 @@
 
             //virtual void damage(float damage, Pawn* originator = 0);
-            virtual void damage(float damage, float healthdamage = 0.0f, float shielddamage = 0.0f, Pawn* originator = NULL);
+            virtual void damage(float damage, float healthdamage = 0.0f, float shielddamage = 0.0f, Pawn* originator = NULL, const btCollisionShape* cs = NULL);
 
             bool bAlive_;
Index: code/trunk/src/orxonox/worldentities/pawns/SpaceShip.cc
===================================================================
--- code/trunk/src/orxonox/worldentities/pawns/SpaceShip.cc	(revision 9950)
+++ code/trunk/src/orxonox/worldentities/pawns/SpaceShip.cc	(revision 10216)
@@ -342,4 +342,22 @@
     /**
     @brief
+        Looks for an attached Engine with a certain name.
+    @param name
+        The name of the engine to be returned.
+    @return
+        Pointer to the engine with the given name, or NULL if not found.
+    */
+    Engine* SpaceShip::getEngineByName(const std::string& name)
+    {
+        for(size_t i = 0; i < this->engineList_.size(); ++i)
+            if(this->engineList_[i]->getName() == name)
+                return this->engineList_[i];
+
+        orxout(internal_warning) << "Couldn't find Engine with name \"" << name << "\"." << endl;
+        return NULL;
+    }
+
+    /**
+    @brief
         Remove and destroy all Engines of the SpaceShip.
     */
@@ -355,4 +373,6 @@
     @param engine
         A pointer to the Engine to be removed.
+    @note
+        Don't forget to reset the Engine's ship pointer after it was removed (or destroy the engine).
     */
     void SpaceShip::removeEngine(Engine* engine)
Index: code/trunk/src/orxonox/worldentities/pawns/SpaceShip.h
===================================================================
--- code/trunk/src/orxonox/worldentities/pawns/SpaceShip.h	(revision 9950)
+++ code/trunk/src/orxonox/worldentities/pawns/SpaceShip.h	(revision 10216)
@@ -124,4 +124,5 @@
             bool hasEngine(Engine* engine) const; // Check whether the SpaceShip has a particular Engine.
             Engine* getEngine(unsigned int i); // Get the i-th Engine of the SpaceShip.
+            Engine* getEngineByName(const std::string& name);
             /**
             @brief Get the list of all Engines that are mounted on the SpaceShip.
