Index: code/branches/OrxoBlox_FS19/src/modules/OrxoBlox/OrxoBloxBall.cc
===================================================================
--- code/branches/OrxoBlox_FS19/src/modules/OrxoBlox/OrxoBloxBall.cc	(revision 12210)
+++ code/branches/OrxoBlox_FS19/src/modules/OrxoBlox/OrxoBloxBall.cc	(revision 12212)
@@ -1,8 +1,2 @@
-
-//TODO: Sounds (all the sounds are still from the pong module...)
-//TODO: Blocks (the Ball-Block comunication is based on how the blocks are implemented)
-//TODO: The bottom boundary/ the Ball collecter
-//TODO: Ability to shoot the ball (the ball is still constructed like the pong ball)
-
 /*
  *   ORXONOX - the hottest 3D action shooter ever to exist
@@ -45,5 +39,5 @@
 #include "gametypes/Gametype.h"
 
-#include "OrxoBloxBlocks.h"
+#include "OrxoBloxBat.h"
 
 #include "sound/WorldSound.h"
@@ -67,10 +61,10 @@
         this->speed_ = 0;
         this->accelerationFactor_ = 1.0f;
-        this->block_ = nullptr;
-        this->bDeleteBlock_ = false;
-        this->blockID_ = new unsigned int[100];
-	for (int i = 0; i < 100; i++) {
-		this->blockID_[i] = OBJECTID_UNKNOWN;
-	}
+        this->bat_ = nullptr;
+        this->bDeleteBats_ = false;
+        this->batID_ = new unsigned int[2];
+        this->batID_[0] = OBJECTID_UNKNOWN;
+        this->batID_[1] = OBJECTID_UNKNOWN;
+        this->relMercyOffset_ = 0.05f;
 
         this->registerVariables();
@@ -102,8 +96,8 @@
         if (this->isInitialized())
         {
-            if (this->bDeleteBlock_)
-                delete[] this->block_;
-
-            delete[] this->blockID_;
+            if (this->bDeleteBats_)
+                delete[] this->bat_;
+
+            delete[] this->batID_;
         }
     }
@@ -126,8 +120,9 @@
         registerVariable( this->fieldWidth_ );
         registerVariable( this->fieldHeight_ );
-        registerVariable( this->blocklength_ );
+        registerVariable( this->batlength_ );
         registerVariable( this->speed_ );
-        registerVariable( this->blockID_[0] );
-        registerVariable( this->blockID_[1], VariableDirection::ToClient, new NetworkCallback<OrxoBloxBall>( this, &OrxoBloxBall::applyBlock) );
+        registerVariable( this->relMercyOffset_ );
+        registerVariable( this->batID_[0] );
+        registerVariable( this->batID_[1], VariableDirection::ToClient, new NetworkCallback<OrxoBloxBall>( this, &OrxoBloxBall::applyBats) );
     }
 
@@ -135,5 +130,5 @@
     @brief
         Is called every tick.
-        Handles the movement of the ball and its interaction with the boundaries and blocks.
+        Handles the movement of the ball and its interaction with the boundaries and bats.
     @param dt
         The time since the last tick.
@@ -148,21 +143,6 @@
         Vector3 acceleration = this->getAcceleration();
 
-        // If the ball has hit the boundaries on either the right side or the left 
-        if (position.x > this->fieldWidth_ / 2 || position.x < -this->fieldWidth_ / 2)
-        {
-            defBoundarySound_->play(); //play boundary sound
-            // Its velocity in x-direction is inverted (i.e. it bounces off).
-            velocity.x = -velocity.x;
-            // And its position is set as to not overstep the boundary it has just crossed.
-            if (position.x > this->fieldWidth_ / 2)
-                position.x = this->fieldWidth_ / 2;
-            if (position.x < -this->fieldWidth_ / 2)
-                position.x = -this->fieldWidth_ / 2;
-
-            this->fireEvent();
-        }
-
-	// If the ball has hit the boundary on the top
-        if (position.z > this->fieldHeight_ / 2)
+        // If the ball has gone over the top or bottom boundary of the playing field (i.e. the ball has hit the top or bottom delimiters).
+        if (position.z > this->fieldHeight_ / 2 || position.z < -this->fieldHeight_ / 2)
         {
             defBoundarySound_->play(); //play boundary sound
@@ -170,13 +150,78 @@
             velocity.z = -velocity.z;
             // And its position is set as to not overstep the boundary it has just crossed.
-            position.z = this->fieldHeight_ / 2;
+            if (position.z > this->fieldHeight_ / 2)
+                position.z = this->fieldHeight_ / 2;
+            if (position.z < -this->fieldHeight_ / 2)
+                position.z = -this->fieldHeight_ / 2;
 
             this->fireEvent();
         }
 
-        // If the ball has crossed the bottom boundary
-        if (position.z < -this->fieldHeight_ / 2)
-        {
-	//TODO: Ball Collector
+        // If the ball has crossed the left or right boundary of the playing field (i.e. a player has just scored, if the bat isn't there to parry).
+        if (position.x > this->fieldWidth_ / 2 || position.x < -this->fieldWidth_ / 2)
+        {
+            float distance = 0;
+
+            if (this->bat_ != nullptr) // If there are bats.
+            {
+                // If the right boundary has been crossed.
+                if (position.x > this->fieldWidth_ / 2 && this->bat_[1] != nullptr)
+                {
+                    // Calculate the distance (in z-direction) between the ball and the center of the bat, weighted by half of the effective length of the bat (with additional 10%)
+                    distance = (position.z - this->bat_[1]->getPosition().z) / (this->fieldHeight_ * (this->batlength_ * 1.10f) / 2);
+                    if (fabs(distance) <= 1) // If the bat is there to parry.
+                    {
+                        defBatSound_->play(); //play bat sound
+                        // Set the ball to be exactly at the boundary.
+                        position.x = this->fieldWidth_ / 2;
+                        // Invert its velocity in x-direction (i.e. it bounces off).
+                        velocity.x = -velocity.x;
+                        // Adjust the velocity in the z-direction, depending on where the ball hit the bat.
+                        velocity.z = distance * distance * sgn(distance) * OrxoBloxBall::MAX_REL_Z_VELOCITY * this->speed_;
+                        acceleration = this->bat_[1]->getVelocity() * this->accelerationFactor_ * -1;
+
+                        this->fireEvent();
+                    }
+                    // If the left player scores.
+                    else if (GameMode::isMaster() && position.x > this->fieldWidth_ / 2 * (1 + this->relMercyOffset_))
+                    {
+                        defScoreSound_->play();//play score sound
+                        if (this->getGametype() && this->bat_[0])
+                        {
+                            this->getGametype()->playerScored(this->bat_[0]->getPlayer());
+                            return;
+                        }
+                    }
+                }
+                // If the left boundary has been crossed.
+                else if (position.x < -this->fieldWidth_ / 2 && this->bat_[0] != nullptr)
+                {
+                    // Calculate the distance (in z-direction) between the ball and the center of the bat, weighted by half of the effective length of the bat (with additional 10%)
+                    distance = (position.z - this->bat_[0]->getPosition().z) / (this->fieldHeight_ * (this->batlength_ * 1.10f) / 2);
+                    if (fabs(distance) <= 1) // If the bat is there to parry.
+                    {
+                        defBatSound_->play(); //play bat sound
+                        // Set the ball to be exactly at the boundary.
+                        position.x = -this->fieldWidth_ / 2;
+                        // Invert its velocity in x-direction (i.e. it bounces off).
+                        velocity.x = -velocity.x;
+                        // Adjust the velocity in the z-direction, depending on where the ball hit the bat.
+                        velocity.z = distance * distance * sgn(distance) * OrxoBloxBall::MAX_REL_Z_VELOCITY * this->speed_;
+                        acceleration = this->bat_[0]->getVelocity() * this->accelerationFactor_ * -1;
+
+                        this->fireEvent();
+                    }
+                    // If the right player scores.
+                    else if (GameMode::isMaster() && position.x < -this->fieldWidth_ / 2 * (1 + this->relMercyOffset_))
+                    {
+                        defScoreSound_->play();//play score sound
+                        if (this->getGametype() && this->bat_[1])
+                        {
+                            this->getGametype()->playerScored(this->bat_[1]->getPlayer());
+                            return;
+                        }
+                    }
+                }
+            }
         }
 
@@ -215,46 +260,45 @@
     /**
     @brief
-        Set the blocks for the ball.
+        Set the bats for the ball.
     @param bats
-        An array (of size n (n=#Blocks) of weak pointers, to be set as the new blocks.
-    */
-    void OrxoBloxBall::setBlock(WeakPtr<OrxoBloxBlock>* block, int n)
-    {
-        if (this->bDeleteBlock_) // If there are already some blocks, delete them.
-        {
-            delete[] this->block_;
-            this->bDeleteBlock_ = false;
-        }
-
-        this->block_ = block;
+        An array (of size 2) of weak pointers, to be set as the new bats.
+    */
+    void OrxoBloxBall::setBats(WeakPtr<OrxoBloxBat>* bats)
+    {
+        if (this->bDeleteBats_) // If there are already some bats, delete them.
+        {
+            delete[] this->bat_;
+            this->bDeleteBats_ = false;
+        }
+
+        this->bat_ = bats;
         // Also store their object IDs, for synchronization.
-	for (int i = 0; i < n; i++) {
-        	this->blockID_[i] = this->block_[i]->getObjectID();
-	}
-    }
-
-    /**
-    @brief
-        Get the blocks over the network.
-    */
-    void OrxoBloxBall::applyBlock(int n)
-    {
-        // Make space for the blocks, if they don't exist, yet.
-        if (this->block_ == nullptr)
-        {
-            this->block_ = new WeakPtr<OrxoBloxBlock>[n];
-            this->bDeleteBlock_ = true;
-        }
-	
-	for (int i = 0; i < n; i++) {
-		if (this->blockID_[i] != OBJECTID_UNKNOWN)
-            	this->bat_[i] = orxonox_cast<OrxoBloxBlock*>(Synchronisable::getSynchronisable(this->blockID_[i]));
-	}
-    }
-
-    void OrxoBloxBall::setDefScoreSound(const std::string &pongSound)
+        this->batID_[0] = this->bat_[0]->getObjectID();
+        this->batID_[1] = this->bat_[1]->getObjectID();
+    }
+
+    /**
+    @brief
+        Get the bats over the network.
+    */
+    void OrxoBloxBall::applyBats()
+    {
+        // Make space for the bats, if they don't exist, yet.
+        if (this->bat_ == nullptr)
+        {
+            this->bat_ = new WeakPtr<OrxoBloxBat>[2];
+            this->bDeleteBats_ = true;
+        }
+
+        if (this->batID_[0] != OBJECTID_UNKNOWN)
+            this->bat_[0] = orxonox_cast<OrxoBloxBat*>(Synchronisable::getSynchronisable(this->batID_[0]));
+        if (this->batID_[1] != OBJECTID_UNKNOWN)
+            this->bat_[1] = orxonox_cast<OrxoBloxBat*>(Synchronisable::getSynchronisable(this->batID_[1]));
+    }
+
+    void OrxoBloxBall::setDefScoreSound(const std::string &OrxoBloxSound)
     {
         if( defScoreSound_ )
-            defScoreSound_->setSource(pongSound);
+            defScoreSound_->setSource(OrxoBloxSound);
         else
             assert(0); // This should never happen, because soundpointer is only available on master
@@ -270,8 +314,8 @@
     }
 
-    void OrxoBloxBall::setDefBatSound(const std::string &pongSound)
+    void OrxoBloxBall::setDefBatSound(const std::string &OrxoBloxSound)
     {
         if( defBatSound_ )
-            defBatSound_->setSource(pongSound);
+            defBatSound_->setSource(OrxoBloxSound);
         else
             assert(0); // This should never happen, because soundpointer is only available on master
@@ -287,8 +331,8 @@
     }
 
-    void OrxoBloxBall::setDefBoundarySound(const std::string &pongSound)
+    void OrxoBloxBall::setDefBoundarySound(const std::string &OrxoBloxSound)
     {
         if( defBoundarySound_ )
-            defBoundarySound_->setSource(pongSound);
+            defBoundarySound_->setSource(OrxoBloxSound);
         else
             assert(0); // This should never happen, because soundpointer is only available on master
