Index: code/trunk/src/orxonox/worldentities/CMakeLists.txt
===================================================================
--- code/trunk/src/orxonox/worldentities/CMakeLists.txt	(revision 8457)
+++ code/trunk/src/orxonox/worldentities/CMakeLists.txt	(revision 8458)
@@ -12,4 +12,5 @@
   SpawnPoint.cc
   TeamSpawnPoint.cc
+  SpaceBoundaries.cc
 )
 
Index: code/trunk/src/orxonox/worldentities/SpaceBoundaries.cc
===================================================================
--- code/trunk/src/orxonox/worldentities/SpaceBoundaries.cc	(revision 8458)
+++ code/trunk/src/orxonox/worldentities/SpaceBoundaries.cc	(revision 8458)
@@ -0,0 +1,297 @@
+/*
+ *   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:
+ *      Maurus Kaufmann
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "SpaceBoundaries.h"
+
+#include "worldentities/MobileEntity.h"
+#include "worldentities/ControllableEntity.h"
+#include "core/ObjectListIterator.h"
+#include "core/XMLPort.h"
+#include "worldentities/pawns/Pawn.h"
+#include "infos/PlayerInfo.h"
+#include "interfaces/RadarViewable.h"
+#include "graphics/Billboard.h"
+
+namespace orxonox
+{
+    CreateFactory(SpaceBoundaries);
+
+    SpaceBoundaries::SpaceBoundaries(BaseObject* creator) : StaticEntity(creator)
+    {
+        /* Standardwerte, die zum Tragen kommen,
+         * falls im XML-File keine Werte spezifiziert wurden. */
+        this->setMaxDistance(3000);
+        this->setWarnDistance(2000);
+        this->setShowDistance(2500);
+        this->setHealthDecrease(1);
+        this->setReaction(0);
+        
+        RegisterObject(SpaceBoundaries);
+        
+        // Show Boundaries on the radar.
+        this->centerRadar_ = new RadarViewable(this, this);
+        this->centerRadar_->setRadarObjectShape(RadarViewable::Dot);
+        this->centerRadar_->setRadarVisibility(false);
+    }
+    SpaceBoundaries::~SpaceBoundaries()
+    {
+        delete this->centerRadar_;
+        
+        this->pawnsIn_.clear();
+        
+        for( std::vector<billboardAdministration>::iterator current = this->billboards_.begin(); current != this->billboards_.end(); current++)
+        {
+            if( current->billy != NULL)
+            {
+                delete current->billy;
+            }
+        }
+        this->billboards_.clear();
+    }
+    
+    void SpaceBoundaries::checkWhoIsIn()
+    {
+        pawnsIn_.clear();
+        for(ObjectListIterator<Pawn> current = ObjectList<Pawn>::begin(); current != ObjectList<Pawn>::end(); ++current)
+        {
+            Pawn* currentPawn = *current;
+            float distance = this->computeDistance(currentPawn);
+            if(distance <= this->maxDistance_)
+            {
+                pawnsIn_.push_back(currentPawn);
+            }
+        }
+    }
+    
+    void SpaceBoundaries::positionBillboard(const Vector3 position)
+    {
+        std::vector<billboardAdministration>::iterator current;
+        for( current = this->billboards_.begin(); current != this->billboards_.end(); current++)
+        {
+            if(!current->usedYet)
+            {
+                break;
+            }
+        }
+        if( current == this->billboards_.end() )
+        {
+            Billboard *tmp = new Billboard(this);
+            this->setBillboardOptions( tmp );
+            tmp->setPosition(position);
+            billboardAdministration tmp2 = { true, tmp };
+            this->billboards_.push_back( tmp2 );
+            
+        } else {
+            current->billy->setPosition(position);
+            current->billy->setVisible(true);
+            current->usedYet = true;
+        }
+    }
+    
+    void SpaceBoundaries::setBillboardOptions(Billboard *billy)
+    {
+        if(billy != NULL)
+        {
+            billy->setMaterial("Shield");
+            billy->setVisible(true);
+        }
+    }
+    
+    void SpaceBoundaries::removeAllBillboards()
+    {
+        for( std::vector<billboardAdministration>::iterator current = this->billboards_.begin(); current != this->billboards_.end(); current++ )
+        {
+            current->usedYet = false;
+            current->billy->setVisible(false);
+        }
+    }
+    
+    void SpaceBoundaries::setMaxDistance(float r)
+    {
+        this->maxDistance_ = r;
+    }
+    float SpaceBoundaries::getMaxDistance()
+    {
+        return this->maxDistance_;
+    }
+    
+    void SpaceBoundaries::setWarnDistance(float r)
+    {
+        this->warnDistance_ = r;
+    }
+    float SpaceBoundaries::getWarnDistance()
+    {
+        return this->warnDistance_;
+    }
+    
+    void SpaceBoundaries::setShowDistance(float r)
+    {
+        this->showDistance_ = r;
+    }
+    float SpaceBoundaries::getShowDistance()
+    {
+        return this->showDistance_;
+    }
+    
+    void SpaceBoundaries::setHealthDecrease(float amount)
+    {
+        this->healthDecrease_ = amount/1000;
+    }
+    float SpaceBoundaries::getHealthDecrease()
+    {
+        return this->healthDecrease_;
+    }
+    
+    void SpaceBoundaries::setReaction(int mode)
+    {
+        this->reaction_ = mode;
+    }
+    int SpaceBoundaries::getReaction()
+    {
+        return this->reaction_;
+    }
+
+    void SpaceBoundaries::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(SpaceBoundaries, XMLPort, xmlelement, mode);
+
+        XMLPortParam(SpaceBoundaries, "maxDistance", setMaxDistance, getMaxDistance, xmlelement, mode);
+        XMLPortParam(SpaceBoundaries, "warnDistance", setWarnDistance, getWarnDistance, xmlelement, mode);
+        XMLPortParam(SpaceBoundaries, "healthDecrease", setHealthDecrease, getHealthDecrease, xmlelement, mode);
+        XMLPortParam(SpaceBoundaries, "reactionMode", setReaction, getReaction, xmlelement, mode);
+    }
+    
+    void SpaceBoundaries::tick(float dt)
+    {
+        this->checkWhoIsIn();
+        this->removeAllBillboards();
+        COUT(0) << "Groesse der Liste: " << (int) pawnsIn_.size() << std::endl;
+        
+        float distance;
+        bool humanItem;
+        for( std::list<WeakPtr<Pawn> >::iterator current = pawnsIn_.begin(); current != pawnsIn_.end(); current++ )
+        {
+            Pawn* currentPawn = current->get();
+            if( currentPawn && currentPawn->getNode() ) 
+            {
+                distance = this->computeDistance(currentPawn);
+                humanItem = this->isHumanPlayer(currentPawn);
+                COUT(0) << "Distanz:" << distance << std::endl; // message for debugging
+                if(distance > this->warnDistance_ && distance < this->maxDistance_) // Zeige Warnung an!
+                {
+                    COUT(0) << "You are near by the boundaries!" << std::endl; // message for debugging
+                    if(humanItem)
+                    {
+                        COUT(0) << "humanItem ist true" << std::endl;
+                        this->displayWarning("Attention! You are near by the boundaries!");
+                    }
+                }
+                if( (this->maxDistance_ - distance) < this->showDistance_ )
+                {
+                    this->displayBoundaries(currentPawn); // Zeige Grenze an!
+                }
+                if(distance > this->maxDistance_ && (this->reaction_ == 1) )
+                {
+                    if( humanItem )
+                    {
+                        COUT(0) << "Health should be decreasing!" << std::endl;
+                        this->displayWarning("You are out of the area now!");
+                    }
+                    currentPawn->removeHealth( (distance - this->maxDistance_) * this->healthDecrease_);
+                }
+                if( (this->reaction_ == 0) && (distance + 100 > this->maxDistance_)) // Annahme: Ein Pawn kann von einem Tick bis zum nächsten nicht mehr als 100 Distanzeinheiten zurücklegen.
+                {
+                    this->conditionalBounceBack(currentPawn, distance, dt);
+                }
+            }
+        }
+    }
+    
+    float SpaceBoundaries::computeDistance(WorldEntity *item)
+    {
+        if(item != NULL)
+        {
+            Vector3 itemPosition = item->getPosition();
+            return (itemPosition.distance(this->getPosition()));
+        } else {
+            return -1;
+        }
+    }
+    
+    void SpaceBoundaries::displayWarning(const std::string warnText)
+    {   
+        
+    }
+    
+    void SpaceBoundaries::displayBoundaries(Pawn *item)
+    {
+        
+        Vector3 direction = item->getPosition() - this->getPosition();
+        direction.normalise();
+        
+        Vector3 boundaryPosition = this->getPosition() + direction * this->maxDistance_;
+        
+        this->positionBillboard(boundaryPosition);
+    }
+    
+    void SpaceBoundaries::conditionalBounceBack(Pawn *item, float currentDistance, float dt)
+    {
+        Vector3 normal = item->getPosition() - this->getPosition();
+        normal.normalise();
+        Vector3 velocity = item->getVelocity();
+        float normalSpeed = item->getVelocity().dotProduct(normal);
+        
+        /* Checke, ob das Pawn innerhalb des nächsten Ticks, das erlaubte Gebiet verlassen würde.
+           Falls ja: Spicke es zurück. */
+        if( currentDistance + normalSpeed * dt > this->maxDistance_ )
+        {
+            float dampingFactor = 0.5;
+            velocity = velocity.reflect(normal);
+            Vector3 acceleration = item->getAcceleration();
+            acceleration = acceleration.reflect(normal);
+            
+            item->lookAt( velocity + this->getPosition() );
+            
+            item->setAcceleration(acceleration * dampingFactor);
+            item->setVelocity(velocity * dampingFactor);
+        }
+    }
+    
+    bool SpaceBoundaries::isHumanPlayer(Pawn *item)
+    {
+        if(item != NULL)
+        {
+            if(item->getPlayer())
+            {
+                return item->getPlayer()->isHumanPlayer();
+            }
+        }
+        return false;
+    }
+    
+}
Index: code/trunk/src/orxonox/worldentities/SpaceBoundaries.h
===================================================================
--- code/trunk/src/orxonox/worldentities/SpaceBoundaries.h	(revision 8458)
+++ code/trunk/src/orxonox/worldentities/SpaceBoundaries.h	(revision 8458)
@@ -0,0 +1,129 @@
+/*
+ *   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:
+ *      Maurus Kaufmann
+ *   Co-authors:
+ *      ...
+ *
+ */
+ 
+ /* TODO:   - Textmessages und Billboards sollen teils nur bei einem humanPlayer angezeigt werden, nicht bei allen (vgl. Netzwerk-Spiel mit mehreren humanPlayers)
+                beachte hierzu folgende statische Funktion: 'static unsigned int  Host::getPlayerID()'
+                (file:///home/kmaurus/orxonox/spaceBoundaries/build/doc/api/html/classorxonox_1_1_host.html#9c1e3b39e3b42e467dfbf42902911ce2)
+                
+            - Kommentieren (Betrachte als Beispiel/Vorbild 'libraries/core/WeakPtr.h')
+            
+            - Wiki-SpaceBoundaries-Eintrag aktualisieren
+ */
+
+#ifndef _SpaceBoundaries_H__
+#define _SpaceBoundaries_H__
+
+
+#include "core/CoreIncludes.h"
+#include "core/WeakPtr.h"
+#include "tools/interfaces/Tickable.h"
+#include "interfaces/RadarViewable.h"
+#include "worldentities/StaticEntity.h"
+#include "worldentities/WorldEntity.h"
+
+#include <string>
+#include <list>
+#include <map>
+#include <vector>
+
+namespace orxonox
+{
+
+/**
+@brief SpaceBoundaries gives level creators the possibility to bar Pawns from leaving a defined area (until now this area is a ball).
+
+       Five attributes can/should be defined in the XML-File:
+       - 'warnDistance' : If the distance between the pawn of the human player and 'position' is bigger than 'warnDistance', a message is displayed to
+                          inform the player that he'll soon be leaving the allowed area. 
+       - 'maxDistance' : defines the area, where a pawn is allowed to be (radius of a ball).
+       - 'showDistance' : If the distance between the pawn and the boundary of the allowed area is smaller than 'showDistance', the boundary is shown. 
+       - 'healthDecrease' : a measure to define how fast the health of a pawn should decrease after leaving the allowed area (unnecessary if 'reactionMode' == 0).
+                            Recommended values: 0.1 (slow health decrease) to 5 (very fast health decrease)
+       - 'reactionMode' : Integer-Value. Defines what effect appears if a space ship has crossed the boundaries.
+                            0: Reflect the space ship (default).
+                            1: Decrease Health of the space ship after having left the allowed area.
+*/
+
+    class _OrxonoxExport SpaceBoundaries : public StaticEntity, public Tickable
+    {
+        public:
+            SpaceBoundaries(BaseObject* creator);
+            ~SpaceBoundaries();
+            
+            void checkWhoIsIn(); //!< Update the list 'pawnsIn_'.
+            
+            void positionBillboard(const Vector3 position); //!< Display a Billboard at the position 'position'.
+            void setBillboardOptions(Billboard *billy);
+            void removeAllBillboards(); //!< Hide all all elements of '*billboard_' and set their attribute 'usedYet' to 0.
+            
+            void setMaxDistance(float r);
+            float getMaxDistance();
+            
+            void setWarnDistance(float r);
+            float getWarnDistance();
+            
+            void setShowDistance(float r);
+            float getShowDistance();
+            
+            void setHealthDecrease(float amount);
+            float getHealthDecrease();
+            
+            void setReaction(int mode);
+            int getReaction();
+
+            void XMLPort(Element& xmlelement, XMLPort::Mode mode);
+            
+            void tick(float dt);
+
+        private:
+            struct billboardAdministration{ bool usedYet; Billboard* billy; };
+            
+            std::list<WeakPtr<Pawn> > pawnsIn_; //!< List of the pawns that this instance of SpaceBoundaries has to handle.
+            
+            std::vector<billboardAdministration> billboards_;
+        
+            int reaction_; //!< Werte: 0, 1. 0: Reflektion an Boundaries (Standard). 1: Health-Abzug-Modus.
+            float maxDistance_; //!< maximal zulaessige Entfernung von 'this->getPosition()'.
+            float warnDistance_; //!< Entfernung von 'this->getPosition()', ab der eine Warnung angezeigt wird, dass man bald das zulaessige Areal verlaesst.
+            float showDistance_; //!< Definiert, wann die Grenzen visualisiert werden sollen.
+            
+            float healthDecrease_; //!< Mass fuer die Anzahl Health-Points, die nach ueberschreiten der Entfernung 'maxDistance_' von 'this->getPosition()' abgezogen werden.
+                                   //!< Empfohlene Werte: 0.1 (langsame Health-Verminderung) bis 5 (sehr schnelle Health-Verminderung)
+            
+            RadarViewable* centerRadar_; //!< Repraesentation von SpaceBoundaries auf dem Radar.
+        
+            float computeDistance(WorldEntity *item); //!< Auf den Mittelpunkt 'this->getPosition()' bezogen.
+            void displayWarning(const std::string warnText);
+            void displayBoundaries(Pawn *item);
+            void conditionalBounceBack(Pawn *item, float currentDistance, float dt);
+            bool isHumanPlayer(Pawn *item);
+            
+    };
+}
+
+#endif /* _SpaceBoundaries_H__ */
