Index: code/branches/ScriptableController_HS17/src/orxonox/infos/GametypeInfo.cc
===================================================================
--- code/branches/ScriptableController_HS17/src/orxonox/infos/GametypeInfo.cc	(revision 11605)
+++ code/branches/ScriptableController_HS17/src/orxonox/infos/GametypeInfo.cc	(revision 11606)
@@ -318,5 +318,5 @@
         {
             this->getLevel()->getScriptableController()->setPlayer(player);
-            this-getLevel()->getScriptableController()->runScript(this->getLevel()->getScript());
+            this->getLevel()->getScriptableController()->runScript(this->getLevel()->getScript());
         }
     }
Index: code/branches/ScriptableController_HS17/src/orxonox/items/ShipPart.cc
===================================================================
--- code/branches/ScriptableController_HS17/src/orxonox/items/ShipPart.cc	(revision 11605)
+++ code/branches/ScriptableController_HS17/src/orxonox/items/ShipPart.cc	(revision 11606)
@@ -42,4 +42,6 @@
 #include "items/PartDestructionEvent.h"
 #include "chat/ChatManager.h"
+#include "Level.h"
+#include "scriptablecontroller/scriptable_controller.h"
 
 
@@ -215,4 +217,9 @@
             }
         }
+
+        // This is a bit hacky, but it takes away damage control from the pawn, so it has to handle
+        // that as well.
+        this->getLevel()->getScriptableController()->pawnHit(parent_, originator, parent_->getHealth(), parent_->getShieldHealth());
+
         if (this->health_ < 0)
             this->death();
Index: code/branches/ScriptableController_HS17/src/orxonox/scriptablecontroller/scriptable_controller.cc
===================================================================
--- code/branches/ScriptableController_HS17/src/orxonox/scriptablecontroller/scriptable_controller.cc	(revision 11605)
+++ code/branches/ScriptableController_HS17/src/orxonox/scriptablecontroller/scriptable_controller.cc	(revision 11606)
@@ -4,4 +4,5 @@
 #include "infos/PlayerInfo.h"
 #include "core/command/Executor.h"
+#include "worldentities/pawns/Pawn.h"
 
 namespace orxonox
@@ -63,7 +64,53 @@
 }
 
-void ScriptableController::registerControllableEntity(std::string id, ControllableEntity *entity)
+void ScriptableController::registerPawn(std::string id, Pawn *pawn)
 {
-    this->worldEntities_[id] = entity;
+    this->worldEntities_[id] = pawn;
+    this->pawns_[id] = pawn;
+    this->pawnsReverse_[pawn] = id;
+}
+
+void ScriptableController::pawnKilled(Pawn *pawn)
+{
+    auto pawn_id_iter = this->pawnsReverse_.find(pawn);
+    if(pawn_id_iter == this->pawnsReverse_.end())
+    {
+        orxout(internal_warning) << "Unregistered pawn reported that it's destroyed" << std::endl;
+        return;
+    }
+
+    for(auto &api : this->apis_)
+        api->pawnKilled(pawn_id_iter->second);
+
+    this->pawns_.erase(pawn_id_iter->second);
+    this->pawnsReverse_.erase(pawn_id_iter);
+}
+
+void ScriptableController::pawnHit(Pawn *target, Pawn *source, double new_health, double new_shield)
+{
+    auto target_id_iter = this->pawnsReverse_.find(target);
+    auto source_id_iter = this->pawnsReverse_.find(source);
+
+    if(target_id_iter == this->pawnsReverse_.end() ||
+       source_id_iter == this->pawnsReverse_.end() )
+    {
+        orxout(internal_warning) << "Unregistered pawn reported that it's hit" << std::endl;
+        return;
+    }
+
+    for(auto &api : this->apis_)
+        api->pawnHit(target_id_iter->second, source_id_iter->second, new_health, new_shield);
+}
+
+void ScriptableController::killPawn(std::string id)
+{
+    auto pawn = this->pawns_.find(id);
+    if(pawn == this->pawns_.end())
+    {
+        orxout(user_warning) << "Tried to destroy unknown pawn " << id << std::endl;
+        return;
+    }
+
+    pawn->second->kill();
 }
 
@@ -77,11 +124,8 @@
 }
 
-ControllableEntity *ScriptableController::getControllableEntityByID(std::string id) const
+Pawn *ScriptableController::getPawnByID(std::string id) const
 {
-    if(id == "player" || id == "Player" || id == "PLAYER")
-        return this->player_->getControllableEntity();
-
-    auto entity = this->controllabelEntities_.find(id);
-    return entity != this->controllabelEntities_.end() ? entity->second : nullptr;
+    auto pawn = this->pawns_.find(id);
+    return pawn != this->pawns_.end() ? pawn->second : nullptr;
 }
 
Index: code/branches/ScriptableController_HS17/src/orxonox/scriptablecontroller/scriptable_controller.h
===================================================================
--- code/branches/ScriptableController_HS17/src/orxonox/scriptablecontroller/scriptable_controller.h	(revision 11605)
+++ code/branches/ScriptableController_HS17/src/orxonox/scriptablecontroller/scriptable_controller.h	(revision 11606)
@@ -18,15 +18,92 @@
 {
 
+/**
+ * @brief Runs a scripts on a per-level basis and handles the connection to orxonox
+ *
+ * The script is an attribute of the <Level> element with the name 'script' and should be
+ * the path to a lua script. The script will be run as soon as the player spawns. It can
+ * then register on various events and react to them. See ScriptableControllerAPI for
+ * the complete API.
+ *
+ * \sa ScriptableControllerAPI
+ */
 class ScriptableController
 {
 public:
+    /**
+     * @brief Run a lua script
+     * @param file_path Path to the script
+     * @return A lua error code (0 for success)
+     *
+     * Constructs an API for the script and runs it.
+     */
     int runScript(const std::string &file_path);
 
+    /**
+     * @brief Set the player object of the current game
+     * @param player The player
+     *
+     * The player is a special object and can perfom special actions.
+     */
     void setPlayer(PlayerInfo *player);
+
+    /**
+     * @brief Register a WorldEntity to the ScriptableController
+     * @param id The ID of the WorldEntity
+     * @param entity The WorldEntity
+     *
+     * The ScriptableController needs a list of all WorldEntity's so it can
+     * convert an ID to a WorldEntity.
+     */
     void registerWorldEntity(std::string id, WorldEntity *entity);
-    void registerControllableEntity(std::string id, ControllableEntity *entity);
 
+    /**
+     * @brief Register a Pawn to the ScriptableController
+     * @param id The ID of the Pawn
+     * @param pawn The Pawn
+     *
+     * The ScriptableController needs a list of all Pawn's in addition to
+     * the WorldEntity's, because they have additional actions available.
+     */
+    void registerPawn(std::string id, Pawn *pawn);
+
+    /**
+     * @brief Called when a Pawn is killed
+     * @param pawn The Pawn
+     *
+     * Called by the Pawn itself as soon as it's killed.
+     */
+    void pawnKilled(Pawn *pawn);
+
+    /**
+     * @brief Called when a Pawn is hit
+     * @param target The hit Pawn
+     * @param source The shooting Pawn
+     * @param new_health The new health of the hit Pawn
+     * @param new_shield The new shield health of the hit Pawn
+     *
+     * Called by the Pawn itself as soon as it's hit.
+     */
+    void pawnHit(Pawn *target, Pawn *source, double new_health, double new_shield);
+
+    /**
+     * @brief Kill a Pawn
+     * @param id The Pawn to kill
+     */
+    void killPawn(std::string id);
+
+    /**
+     * @brief Convert an ID to a WorldEntity pointer
+     * @param id The ID of the WorldEntity
+     * @return A pointer to the WorldEntity, nullptr if it's not found
+     */
     WorldEntity *getWorldEntityByID(std::string id) const;
-    ControllableEntity *getControllableEntityByID(std::string id) const;
+
+    /**
+     * @brief Convert an ID to a Pawt pointer
+     * @param id The ID of the Pawn
+     * @return A pointer to the Pawn, nullptr if it's not found
+     */
+    Pawn *getPawnByID(std::string id) const;
 
 private:
@@ -34,6 +111,12 @@
     PlayerInfo *player_;
     std::map<std::string, WorldEntity*> worldEntities_;
+    std::map<std::string, Pawn*> pawns_;
+    std::map<Pawn*, std::string> pawnsReverse_;
     std::map<std::string, ControllableEntity*> controllabelEntities_;
 
+    /**
+     * @brief Prints a human readable error message if a lua error occurs
+     * @param lua The lua state where the error occured
+     */
     void printLuaError(lua_State *lua);
 };
Index: code/branches/ScriptableController_HS17/src/orxonox/scriptablecontroller/scriptable_controller_api.cc
===================================================================
--- code/branches/ScriptableController_HS17/src/orxonox/scriptablecontroller/scriptable_controller_api.cc	(revision 11605)
+++ code/branches/ScriptableController_HS17/src/orxonox/scriptablecontroller/scriptable_controller_api.cc	(revision 11606)
@@ -8,4 +8,6 @@
 {
 
+const double ScriptableControllerAPI::periodic_interval = 0.5;
+
 ScriptableControllerAPI::ScriptableControllerAPI(lua_State *lua, ScriptableController *controller)
 {
@@ -15,4 +17,5 @@
     // Haven't found a shorter way yet to write that...
     LuaTB<ScriptableControllerAPI, decltype(&ScriptableControllerAPI::orxPrint)>::registerFunction<&ScriptableControllerAPI::orxPrint>(this, lua, "orxPrint");
+
     LuaTB<ScriptableControllerAPI, decltype(&ScriptableControllerAPI::registerAfterTimeout)>::registerFunction<&ScriptableControllerAPI::registerAfterTimeout>(this, lua, "registerAfterTimeout");
     LuaTB<ScriptableControllerAPI, decltype(&ScriptableControllerAPI::registerAtNearObject)>::registerFunction<&ScriptableControllerAPI::registerAtNearObject>(this, lua, "registerAtNearObject");
@@ -20,9 +23,10 @@
     LuaTB<ScriptableControllerAPI, decltype(&ScriptableControllerAPI::registerAtAreaEnter)>::registerFunction<&ScriptableControllerAPI::registerAtAreaEnter>(this, lua, "registerAtAreaEnter");
     LuaTB<ScriptableControllerAPI, decltype(&ScriptableControllerAPI::registerAtAreaLeave)>::registerFunction<&ScriptableControllerAPI::registerAtAreaLeave>(this, lua, "registerAtAreaLeave");
-//    LuaTB<ScriptableControllerAPI, decltype(&ScriptableControllerAPI::registerAtObjectDestroyed)>::registerFunction<&ScriptableControllerAPI::registerAtObjectDestroyed>(this, lua, "registerAtObjectDestroyed");
-//    LuaTB<ScriptableControllerAPI, decltype(&ScriptableControllerAPI::registerAtPickup)>::registerFunction<&ScriptableControllerAPI::registerAtPickup>(this, lua, "registerAtPickup");
+    LuaTB<ScriptableControllerAPI, decltype(&ScriptableControllerAPI::registerAtPawnKilled)>::registerFunction<&ScriptableControllerAPI::registerAtPawnKilled>(this, lua, "registerAtPawnKilled");
+    LuaTB<ScriptableControllerAPI, decltype(&ScriptableControllerAPI::registerAtPawnHit)>::registerFunction<&ScriptableControllerAPI::registerAtPawnHit>(this, lua, "registerAtPawnHit");
 
-    // Checks for area enter, area leave and near object events
-    this->areaCheckTimer.setTimer(0.5, true, createExecutor(createFunctor(&ScriptableControllerAPI::checkAreas, this)), false);
+    LuaTB<ScriptableControllerAPI, decltype(&ScriptableControllerAPI::killPawn)>::registerFunction<&ScriptableControllerAPI::killPawn>(this, lua, "killPawn");
+
+    this->periodicTimer.setTimer(ScriptableControllerAPI::periodic_interval, true, createExecutor(createFunctor(&ScriptableControllerAPI::periodic, this)), false);
 }
 
@@ -76,5 +80,37 @@
 }
 
-void ScriptableControllerAPI::checkAreas()
+void ScriptableControllerAPI::registerAtPawnKilled(std::function<void (std::string)> callback, std::string id)
+{
+    this->pawnDestroyedHandlers_[id].push_back(callback);
+}
+
+void ScriptableControllerAPI::registerAtPawnHit(std::function<void (std::string, std::string, double, double)> callback, std::string id)
+{
+    this->pawnHitHandlers_[id].push_back(callback);
+}
+
+void ScriptableControllerAPI::killPawn(std::string id)
+{
+    // We don't kill the pawn here directly, because this function is called from LUA and thus
+    // runs in a different thread. So we schedule the kill for later in the main thread
+    // (in 'periodic').
+    this->pawnsToKill_.push_back(id);
+}
+
+void ScriptableControllerAPI::pawnKilled(std::string id)
+{
+    for(auto callback : this->pawnDestroyedHandlers_[id])
+        callback(id);
+
+    this->pawnDestroyedHandlers_.erase(id);
+}
+
+void ScriptableControllerAPI::pawnHit(std::string target_id, std::string source_id, double new_health, double new_shield)
+{
+    for(auto callback : this->pawnHitHandlers_[target_id])
+        callback(target_id, source_id, new_health, new_shield);
+}
+
+void ScriptableControllerAPI::periodic()
 {
     // Near object
@@ -138,4 +174,10 @@
         }
     }
+
+    // Pawns to kill
+    for(auto &pawn : this->pawnsToKill_)
+        this->controller_->killPawn(pawn);
+
+    this->pawnsToKill_.clear();
 }
 
Index: code/branches/ScriptableController_HS17/src/orxonox/scriptablecontroller/scriptable_controller_api.h
===================================================================
--- code/branches/ScriptableController_HS17/src/orxonox/scriptablecontroller/scriptable_controller_api.h	(revision 11605)
+++ code/branches/ScriptableController_HS17/src/orxonox/scriptablecontroller/scriptable_controller_api.h	(revision 11606)
@@ -15,28 +15,151 @@
 class WorldEntity;
 
+/**
+ * @brief API for ScriptableController's lua-scripts
+ *
+ * Defines the interface that lua can use in the scripts to communicate with orxonox.
+ *
+ * \sa ScriptableController
+ */
 class ScriptableControllerAPI
 {
 public:
+    /**
+     * @brief Constructs the API with the given lua state
+     * @param lua The lua state
+     * @param controller The parent controller
+     *
+     * This will not run any scripts, it'll just make the API visible to lua.
+     */
     ScriptableControllerAPI(lua_State *lua, ScriptableController *controller);
+
+    /**
+     * @brief Destructs the API and closes the lua state.
+     */
     ~ScriptableControllerAPI();
 
-    void testOutput(std::function<void(std::string)> callback);
-
+    // --- API ----------------------------------
+
+    /**
+     * @brief Print a message
+     * @param msg The message
+     *
+     * Use this function instead of printing from lua directly, because that will mess up the
+     * output as it is not synchronized.
+     */
     void orxPrint(std::string msg);
+
+    /**
+     * @brief Register a function that will be called after a timeout
+     * @param callback The function to call after the timeout expired
+     * @param timeout The timeout in seconds
+     */
     void registerAfterTimeout(std::function<void (void)> callback, double timeout);
 
+    /**
+     * @brief Register a function that will be called when two object are close to eachother
+     * @param callback The function to call when the objects are close enough
+     * @param id1 The first object
+     * @param id2 The second object
+     * @param distance If the distance between the two objects is smaller than this value,
+     * the function is called
+     *
+     * Note: Distances are only checked every 0.5s!
+     */
     void registerAtNearObject(std::function<void(std::string, std::string)> callback, std::string id1, std::string id2, double distance);
+
+    /**
+     * @brief Register a function that will be called when an object is close to a certain point
+     * @param callback The function to call when the object is close enough
+     * @param id The object
+     * @param x X-coordinate of the point
+     * @param y Y-coordinate of the point
+     * @param z Z-coordinate of the point
+     * @param distance If the distance between the object and the point is smaller than this value, the
+     * function is called.
+     *
+     * Note: Distances are only checked every 0.5s!
+     */
     void registerAtNearPoint(std::function<void (std::string)> callback, std::string id, double x, double y, double z, double distance);
-    void registerAtAreaEnter(std::function<void (std::string)> callback, std::string obj, int x, int y, int z, int dx, int dy, int dz);
-    void registerAtAreaLeave(std::function<void (std::string)> callback, std::string obj, int x, int y, int z, int dx, int dy, int dz);
-
-    void registerAtObjectDestroyed(std::function<void (std::string)> callback, std::string obj);
-    void registerAtPickup(std::function<void (int)> callback, int pickup_id);
-
-    void destroyObject(std::string obj);
-    void removeObject(std::string obj);
-    void setObjectPosition(std::string obj, double x, double y, double z);
+
+    /**
+     * @brief Register a function that will be called when an object enters a cubic area
+     * @param callback The function to call when the object entered the area
+     * @param id The object
+     * @param x X-coordinate of the top-left corner
+     * @param y Y-coordinate of the top-left corner
+     * @param z Z-coordinate of the top-left corner
+     * @param dx Size in X-direction of the cube
+     * @param dy Size in Y-direction of the cube
+     * @param dz Size in Z-direction of the cube
+     *
+     * Note: Distances are only checked every 0.5s!
+     */
+    void registerAtAreaEnter(std::function<void (std::string)> callback, std::string id, int x, int y, int z, int dx, int dy, int dz);
+
+    /**
+     * @brief Register a function that will be called when an object leaves a cubic area
+     * @param callback The function to call when the object left the area
+     * @param id The object
+     * @param x X-coordinate of the top-left corner
+     * @param y Y-coordinate of the top-left corner
+     * @param z Z-coordinate of the top-left corner
+     * @param dx Size in X-direction of the cube
+     * @param dy Size in Y-direction of the cube
+     * @param dz Size in Z-direction of the cube
+     *
+     * Note: Distances are only checked every 0.5s!
+     */
+    void registerAtAreaLeave(std::function<void (std::string)> callback, std::string id, int x, int y, int z, int dx, int dy, int dz);
+
+    /**
+     * @brief Register a function that will be called when a Pawn is killed
+     * @param callback The function to call as soon as the Pawn is dead
+     * @param id The Pawn
+     *
+     * Note: Once a Pawn is dead, the callback is removed, even if the pawn got magically revived.
+     */
+    void registerAtPawnKilled(std::function<void (std::string)> callback, std::string id);
+
+    /**
+     * @brief Register a function that will be called when a Pawn is hit
+     * @param callback The function to call as soon as the Pawn is hit
+     * @param id The Pawn
+     *
+     * Note: Once a Pawn is dead, the all hit-callbacks are removed, even if the pawn got magically revived.
+     */
+    void registerAtPawnHit(std::function<void (std::string, std::string, double, double)> callback, std::string id);
+
+    /**
+     * @brief Kill a pawn
+     * @param id The pawn to kill
+     *
+     * Note: It might up to 0.5s until the pawn is actually killed.
+     */
+    void killPawn(std::string id);
+
+    // ------------------------------------------
+
+    /**
+     * @brief Called by ScriptableController when a pawn is killed
+     * @param id The dead pawn
+     *
+     * Calls the lua callbacks associated with this event.
+     */
+    void pawnKilled(std::string id);
+
+    /**
+     * @brief Called by ScriptableController when a Pawn is hit
+     * @param target_id The hit Pawn
+     * @param source_id The shooting Pawn
+     * @param new_health The new health of the hit Pawn
+     * @param new_shield The new shield health of the hit Pawn
+     */
+    void pawnHit(std::string target_id, std::string source_id, double new_health, double new_shield);
 
 private:
+    /**
+     * @brief Groups everything together that is needed to handle a near-object event
+     */
     struct NearObjectHandler
     {
@@ -51,4 +174,7 @@
     };
 
+    /**
+     * @brief Groups everything together that is needed to handle a near-poinb event
+     */
     struct NearPointHandler
     {
@@ -64,4 +190,7 @@
     };
 
+    /**
+     * @brief Groups everything together that is needed to handle an area enter/leave event
+     */
     struct AreaHandler
     {
@@ -83,7 +212,18 @@
     std::list<NearPointHandler> nearPointHandlers_;
     std::list<AreaHandler> areaHandlers_;
-    Timer areaCheckTimer;
-
-    void checkAreas(void);
+    std::list<std::string> pawnsToKill_;
+    std::map<std::string, std::list<std::function<void (std::string)> > > pawnDestroyedHandlers_;
+    std::map<std::string, std::list<std::function<void (std::string, std::string, double, double)> > > pawnHitHandlers_;
+    Timer periodicTimer;
+    static const double periodic_interval;
+
+    /**
+     * @brief Called every 0.5s
+     *
+     * This handles things that have to be checked periodically (like area events) and
+     * things that are done by lua that have to synchronize with the main thread (like
+     * killing a pawn). Doing this in every tick would be an overkill.
+     */
+    void periodic(void);
 };
 
Index: code/branches/ScriptableController_HS17/src/orxonox/worldentities/ControllableEntity.cc
===================================================================
--- code/branches/ScriptableController_HS17/src/orxonox/worldentities/ControllableEntity.cc	(revision 11605)
+++ code/branches/ScriptableController_HS17/src/orxonox/worldentities/ControllableEntity.cc	(revision 11606)
@@ -45,5 +45,4 @@
 #include "worldentities/CameraPosition.h"
 #include "overlays/OverlayGroup.h"
-#include "scriptablecontroller/scriptable_controller.h"
 
 namespace orxonox
@@ -127,7 +126,4 @@
         XMLPortObject(ControllableEntity, CameraPosition, "camerapositions", addCameraPosition, getCameraPosition, xmlelement, mode);
         XMLPortObject(ControllableEntity, Controller,     "controller",      setXMLController,  getXMLController,  xmlelement, mode);
-
-        if(!this->id_.empty() && this->getLevel() != nullptr)
-            this->getLevel()->getScriptableController()->registerControllableEntity(this->id_, this);
     }
 
Index: code/branches/ScriptableController_HS17/src/orxonox/worldentities/pawns/Pawn.cc
===================================================================
--- code/branches/ScriptableController_HS17/src/orxonox/worldentities/pawns/Pawn.cc	(revision 11605)
+++ code/branches/ScriptableController_HS17/src/orxonox/worldentities/pawns/Pawn.cc	(revision 11606)
@@ -50,4 +50,6 @@
 #include "sound/WorldSound.h"
 #include "core/object/ObjectListIterator.h"
+#include "Level.h"
+#include "scriptablecontroller/scriptable_controller.h"
 
 #include "controllers/FormationController.h"
@@ -159,4 +161,7 @@
 
         XMLPortParam ( RadarViewable, "radarname", setRadarName, getRadarName, xmlelement, mode );
+
+        if(!this->id_.empty() && this->getLevel() != nullptr)
+            this->getLevel()->getScriptableController()->registerPawn(this->id_, this);
     }
 
@@ -281,5 +286,5 @@
         {
             // Health-damage cannot be absorbed by shields.
-            // Shield-damage only reduces shield health. 
+            // Shield-damage only reduces shield health.
             // Normal damage can be (partially) absorbed by shields.
 
@@ -301,4 +306,5 @@
                 this->setHealth(this->health_ - (damage - shielddamage) - healthdamage);
             }
+            this->getLevel()->getScriptableController()->pawnHit(this, originator, this->health_, this->shieldHealth_);
 
             this->lastHitOriginator_ = originator;
@@ -401,4 +407,6 @@
             }
         }
+
+        this->getLevel()->getScriptableController()->pawnKilled(this);
     }
     void Pawn::goWithStyle()
@@ -624,5 +632,5 @@
         {
             // delete all debug models
-            for(Model* model : debugWeaponSlotModels_) 
+            for(Model* model : debugWeaponSlotModels_)
             {
                 model->destroy();
