Index: code/branches/campaignHS15/src/orxonox/controllers/FightingController.cc
===================================================================
--- code/branches/campaignHS15/src/orxonox/controllers/FightingController.cc	(revision 10883)
+++ code/branches/campaignHS15/src/orxonox/controllers/FightingController.cc	(revision 10885)
@@ -21,7 +21,7 @@
  *
  *   Author:
- *      Fabian 'x3n' Landau
+ *      Gani Aliguzhinov
  *   Co-authors:
- *      Dominik Solenicki
+ *      Fabian 'x3n' Landau, Dominik Solenicki
  *
  */
@@ -31,4 +31,11 @@
 
 
+#include "worldentities/pawns/SpaceShip.h"
+
+#include "weaponsystem/WeaponMode.h"
+#include "weaponsystem/WeaponPack.h"
+#include "weaponsystem/Weapon.h"
+#include "weaponsystem/WeaponSlot.h"
+#include "weaponsystem/WeaponSlot.h"
 namespace orxonox
 {
@@ -38,7 +45,8 @@
     FightingController::FightingController( Context* context ): FlyingController( context )
     {
-    	this->attackRange_ = 2000;
+    	this->attackRange_ = 3000;
         this->stopLookingAtTarget();
-
+        this->bSetupWorked = false;
+        this->timeout_ = 0;
         RegisterObject( FightingController );
     }
@@ -78,5 +86,5 @@
         this->bLookAtTarget_ = true;
     }
-    bool FightingController::hasTarget() 
+    bool FightingController::hasTarget() const
     {
         if ( this->target_ )
@@ -106,25 +114,17 @@
     void FightingController::maneuver() 
     {
+        if ( !this->target_ || !this->getControllableEntity())
+            return;
         maneuverCounter_++;
         if (maneuverCounter_ > 5)
             maneuverCounter_ = 0;
 
-        if ( !this->target_ || !this->getControllableEntity())
-            return;
-        
         Vector3 thisPosition = this->getControllableEntity()->getWorldPosition();
-        this->setPositionOfTarget( getPredictedPosition( 
-            thisPosition, 
-            hardcoded_projectile_speed, 
-            this->target_->getWorldPosition() , 
-            this->target_->getVelocity()  
-            )  );
-        this->setOrientationOfTarget( this->target_->getOrientation() );
-
+        this->setPositionOfTarget(this->target_->getWorldPosition());
+        //this->setOrientationOfTarget(this->target_->getOrientation());
         Vector3 diffVector = this->positionOfTarget_ - thisPosition;
         float diffLength = diffVector.length();
         Vector3 diffUnit = diffVector/diffLength;
-
-        bool bTargetIsLookingAtThis = CommonController::isLooking ( this->target_, getControllableEntity(), math::pi/20.0f );
+        bool bTargetIsLookingAtThis = CommonController::isLooking (this->target_, this->getControllableEntity(), math::pi/20.0f);
         
         //too far? well, come closer then
@@ -135,13 +135,13 @@
             this->bKeepFormation_ = true;
             
-            this->setTargetPosition( this->positionOfTarget_ );
+            this->setTargetPosition(this->positionOfTarget_ - diffUnit * 200.0f);
         }
         //too close? How do u expect to dodge anything? Just attack!
-        else if ( diffLength < 500 )
+        else if (diffLength < 500)
         {   
             this->bKeepFormation_ = false;
 
             //at this point, just look and shoot
-            if ( diffLength < 250 )
+            if (diffLength < 250)
             {
                 this->stopMoving();
@@ -150,12 +150,12 @@
             else
             {
-                this->setTargetPosition( this->positionOfTarget_ );
+                this->setTargetPosition(this->positionOfTarget_ - diffUnit * 200.0f);
             }
         }
         //Good distance? Check if target looks at us. It doesn't? Go hunt!
-        else if ( !bTargetIsLookingAtThis )
+        else if (!bTargetIsLookingAtThis)
         {
             this->bKeepFormation_ = false;
-            this->setTargetPosition( this->positionOfTarget_ );
+            this->setTargetPosition(this->positionOfTarget_ - diffUnit * 200.0f);
         }
         //That's unfortunate, he is looking and probably shooting... try to dodge what we can...  
@@ -165,91 +165,62 @@
             if (maneuverCounter_ == 0)
             {
-                this->setTargetPosition( this->positionOfTarget_ );   
+                this->setTargetPosition(this->positionOfTarget_ - diffUnit * 200.0f);   
                 return;
             }
-            dodge( thisPosition, diffUnit );
+            dodge(thisPosition, diffUnit);
         }
     }
     
-    void FightingController::dodge(Vector3& thisPosition, Vector3& diffUnit)
-    {
-        float factorX = 0, factorY = 0, factorZ = 0;
-        float rand = CommonController::randomInRange (0, 1);
-    
-        if (rand <= 0.5)
-        { factorX = 1; }
+    void FightingController::dodge(const Vector3& thisPosition, Vector3& diffUnit)
+    {
+        //d.x*x + d.y*y + d.z*z == 0
+        //z = 1/d.z * (-d.y*y - d.x * x)
+        float x = CommonController::randomInRange (1000, 10000) * (CommonController::randomInRange(0,1) <= 0.5 ? 1 : -1);
+        float y = CommonController::randomInRange (1000, 10000) * (CommonController::randomInRange(0,1) <= 0.5 ? 1 : -1);
+        float z = (1/diffUnit.z) * (-x * diffUnit.x - y * diffUnit.y);
+        this->setTargetPosition(thisPosition + Vector3(x,y,z) + diffUnit * 1000.0f);
+        this->boostControl();
+
+    }
+    bool FightingController::canFire() 
+    {
+        //no target? why fire?
+        if (!this->target_)
+            return false;
+        Vector3 newPositionOfTarget = getPredictedPosition(this->getControllableEntity()->getWorldPosition(), 
+                                                           hardcoded_projectile_speed, this->target_->getWorldPosition(), 
+                                                           this->target_->getVelocity());
+        if (!newPositionOfTarget.isNaN())
+        {
+            this->setPositionOfTarget(newPositionOfTarget);
+        }
+        return squaredDistanceToTarget() < this->attackRange_*this->attackRange_ && this->isLookingAtTarget(math::pi / 20.0f);
+    }
+    // void FightingController::doFire() 
+    // {
+    //     if ( !this->target_ || !this->getControllableEntity() )
+    //     {
+    //         return;
+    //     }
+      
+    //     Pawn* pawn = orxonox_cast<Pawn*>( this->getControllableEntity() );
+
+    //     if ( pawn )
+    //         pawn->setAimPosition( this->positionOfTarget_ );
+    //     float distance = CommonController::distance (this->getControllableEntity(), this->target_);
+    //     this->getControllableEntity() ->fire(distance < 1500 ? (distance < 1000 && distance > 700 ? 3 : 0) : (1));
+    // }
+
+
+    float FightingController::squaredDistanceToTarget()  const
+    {
+        if (!this->getControllableEntity())
+            return 0;
+        if (!this->target_ || !this->getControllableEntity())
+            return (this->getControllableEntity()->getPosition().squaredDistance(this->targetPosition_));
         else
-        { factorX = -1; }
-        rand = CommonController::randomInRange (0, 1);
-        if (rand <= 0.5)
-        { factorY = 1; }
-        else
-        { factorY = -1; }
-        rand = CommonController::randomInRange (0, 1);
-        if (rand <= 0.5)
-        { factorZ = 1; }
-        else
-        { factorZ = -1; }
-
-        Vector3 target = ( diffUnit )* 8000.0f;
-        Vector3* randVector = new Vector3( 
-            factorX * CommonController::randomInRange( 10000, 40000 ), 
-            factorY * CommonController::randomInRange( 10000, 40000 ), 
-            factorZ * CommonController::randomInRange( 10000, 40000 ) 
-        );
-        Vector3 projection = randVector->dotProduct( diffUnit )* diffUnit;
-        Vector3 randV = *randVector;
-        delete randVector;
-        randV -= projection;
-        target += randV;
-        this->setTargetPosition( thisPosition + target );
-    }
-    bool FightingController::canFire() 
-    {
-        //no target? why fire?
-        if ( !this->target_ )
-            return false;
-
-        Vector3 newPositionOfTarget = getPredictedPosition( this->getControllableEntity() ->getWorldPosition() , 
-            hardcoded_projectile_speed, this->target_->getWorldPosition() , this->target_->getVelocity() );
-        if ( newPositionOfTarget != Vector3::ZERO )
-        {
-            this->setPositionOfTarget( newPositionOfTarget );
-        }
-
-        float squaredDistance = squaredDistanceToTarget();
-
-        if ( squaredDistance < this->attackRange_*this->attackRange_ && this->isLookingAtTarget( math::pi / 20.0f)) 
-        {
-            return true;
-        }
-        else
-        {
-            return false;
-        }
-    }
-    void FightingController::doFire() 
-    {
-        if ( !this->target_ || !this->getControllableEntity() )
-        {
-            return;
-        }
-      
-        Pawn* pawn = orxonox_cast<Pawn*>( this->getControllableEntity() );
-
-        if ( pawn )
-            pawn->setAimPosition( this->positionOfTarget_ );
-        this->getControllableEntity() ->fire( 0 );
-    }
-    float FightingController::squaredDistanceToTarget()  const
-    {
-        if ( !this->getControllableEntity()  )
-            return 0;
-        if ( !this->target_ || !this->getControllableEntity() )
-            return ( this->getControllableEntity() ->getPosition() .squaredDistance( this->targetPosition_ ) );
-        else
-            return ( this->getControllableEntity() ->getPosition() .squaredDistance( this->positionOfTarget_ ) );
-    }
-    bool FightingController::isLookingAtTarget( float angle )
+            return (this->getControllableEntity()->getPosition().squaredDistance(this->positionOfTarget_));
+    }
+    bool FightingController::isLookingAtTarget( float angle ) const
     {
         if ( !this->getControllableEntity()  || !this->target_ )
@@ -257,10 +228,10 @@
         return CommonController::isLooking(this->getControllableEntity(), this->getTarget(), angle);
     }
-        void FightingController::setClosestTarget()
+    void FightingController::setClosestTarget()
     {
         this->setTarget (static_cast<ControllableEntity*>( closestTarget() ) ); 
     }
     
-    Pawn* FightingController::closestTarget()
+    Pawn* FightingController::closestTarget() const
     {
         if (!this->getControllableEntity())
@@ -288,3 +259,114 @@
         return 0;  
     }
+    //I checked it out, rockets DO NOT cause any problems! this->getControllableEntity() is always a SpaceShip
+    void FightingController::doFire()
+    {
+        if (!this->bSetupWorked)
+        {
+            this->setupWeapons();
+        }
+        if (!this->target_ || !this->getControllableEntity())
+        {
+            return;
+        }
+        Pawn* pawn = orxonox_cast<Pawn*> (this->getControllableEntity());
+        if (pawn)
+            pawn->setAimPosition (this->positionOfTarget_);
+
+        int firemode;
+        float distance = CommonController::distance (this->getControllableEntity(), this->target_);
+
+        // firemode = distance < 1500 ? (distance > 800 && distance < 1200 ? 
+        //                             (this->rocketsLeft_ > 0 && !this->bFiredRocket_ ? getFiremode("RocketFire") : getFiremode ("HsW01"))
+        //                                                      : getFiremode("HsW01")) : 
+        //                                                      (distance < 2500 ? getFiremode("LightningGun") : getFiremode("HsW01"));
+        if (distance < 800)
+        {
+            if (this->rocketsLeft_ > 0)
+            {
+                firemode = getFiremode ("SimpleRocketFire");
+            }
+            else
+            {
+                if (distance > 450)
+                    firemode = getFiremode ("LightningGun");
+                else
+                    firemode = getFiremode ("HsW01");
+            }
+
+        } 
+        else if (distance < 1200)
+        {
+            if (this->rocketsLeft_ > 0 && !this->bFiredRocket_)
+            {
+                firemode = getFiremode ("RocketFire");
+            }
+            else
+            {
+                firemode = getFiremode ("HsW01");
+            }
+        }
+        else if (distance < 1500)
+        {
+            firemode = getFiremode ("LightningGun");
+        }
+        else
+        {
+            firemode = getFiremode ("HsW01");
+        }
+        if (firemode < 0)
+        {
+            firemode = getFiremode ("HsW01");
+        }
+        if (firemode == getFiremode("RocketFire"))
+        {
+            this->timeout_ = 1.0f;
+            this->rocketsLeft_--;
+            this->bFiredRocket_ = true;
+        }
+        if (firemode == getFiremode("SimpleRocketFire"))
+        {
+            this->rocketsLeft_--;
+        }
+              
+        this->getControllableEntity()->fire(firemode);
+        
+    }
+    void FightingController::setupWeapons() //TODO: Make this function generic!! (at the moment is is based on conventions)
+    {
+        this->bSetupWorked = false;
+        if(this->getControllableEntity())
+        {
+            Pawn* pawn = orxonox_cast<Pawn*>(this->getControllableEntity());
+            if(pawn && pawn->isA(Class(SpaceShip))) //fix for First Person Mode: check for SpaceShip
+            {
+                this->weaponModes_.clear(); // reset previous weapon information
+                WeaponSlot* wSlot = 0;
+                for(int l=0; (wSlot = pawn->getWeaponSlot(l)) ; l++)
+                {
+                    WeaponMode* wMode = 0;
+                    for(int i=0; (wMode = wSlot->getWeapon()->getWeaponmode(i)) ; i++)
+                    {
+                        std::string wName = wMode->getIdentifier()->getName();
+                        if (wName == "RocketFire")
+                            this->rocketsLeft_ = 10;
+                        if(this->getFiremode(wName) == -1) //only add a weapon, if it is "new"
+                            weaponModes_[wName] = wMode->getMode();
+                    }
+                }
+                if(weaponModes_.size())//at least one weapon detected
+                    this->bSetupWorked = true;
+            }//pawn->weaponSystem_->getMunition(SubclassIdentifier< Munition > *identifier)->getNumMunition (WeaponMode *user);
+        }
+    }
+
+    int FightingController::getFiremode(std::string name)
+    {
+        for (std::map< std::string, int >::iterator it = this->weaponModes_.begin(); it != this->weaponModes_.end(); ++it)
+        {
+            if (it->first == name)
+                return it->second;
+        }
+        return -1;
+    }
 }
