Index: code/trunk/src/orxonox/objects/SpaceShipAI.cc
===================================================================
--- code/trunk/src/orxonox/objects/SpaceShipAI.cc	(revision 1505)
+++ code/trunk/src/orxonox/objects/SpaceShipAI.cc	(revision 1552)
@@ -32,4 +32,5 @@
 #include <OgreMath.h>
 #include "Projectile.h"
+#include "ParticleSpawner.h"
 #include "core/CoreIncludes.h"
 #include "core/Iterator.h"
@@ -37,4 +38,5 @@
 #include "core/ConsoleCommand.h"
 #include "core/XMLPort.h"
+#include "particle/ParticleInterface.h"
 
 #define ACTION_INTERVAL 1.0f
@@ -51,6 +53,4 @@
         RegisterObject(SpaceShipAI);
 
-        this->alive_ = true;
-        this->setPosition(Vector3(rnd(-1000, 1000), rnd(-1000, 1000), rnd(-1000, 0000)));
         this->target_ = 0;
         this->bShooting_ = 0;
@@ -70,9 +70,15 @@
     }
 
+    SpaceShipAI::~SpaceShipAI()
+    {
+        for (Iterator<SpaceShipAI> it = ObjectList<SpaceShipAI>::begin(); it; ++it)
+            it->shipDied(this);
+    }
+
     void SpaceShipAI::XMLPort(Element& xmlelement, XMLPort::Mode mode)
     {
         SpaceShip::XMLPort(xmlelement, mode);
-        myShip_=true;
-
+
+        this->myShip_=true;
         this->actionTimer_.setTimer(ACTION_INTERVAL, true, this, createExecutor(createFunctor(&SpaceShipAI::action)));
     }
@@ -85,4 +91,5 @@
             newenemy->setMesh("assff.mesh");
 //            newenemy->setPosition(0, 0, 0);
+            newenemy->setPosition(Vector3(rnd(-3000, 3000), rnd(-3000, 3000), rnd(-3000, 3000)));
             newenemy->setScale(10);
             newenemy->setMaxSpeed(500);
@@ -95,4 +102,8 @@
             Element xmlelement;
             newenemy->XMLPort(xmlelement, XMLPort::LoadObject);
+
+            ParticleSpawner* spawneffect = new ParticleSpawner("Orxonox/fairytwirl", 2.0, 0.0, newenemy->getOrth());
+            spawneffect->setPosition(newenemy->getPosition() - newenemy->getOrth() * 50);
+            spawneffect->create();
         }
     }
@@ -103,6 +114,5 @@
         for (Iterator<SpaceShipAI> it = ObjectList<SpaceShipAI>::begin(); it; )
         {
-            delete *(it++);
-            ++i;
+            (it++)->kill();
             if (num && i >= num)
                 break;
@@ -122,65 +132,76 @@
         // search enemy
         random = rnd(maxrand);
-//std::cout << "search enemy: " << random << std::endl;
         if (random < 20 && (!this->target_))
-        {
             this->searchNewTarget();
-        }
 
         // forget enemy
         random = rnd(maxrand);
-//std::cout << "forget enemy: " << random << std::endl;
         if (random < 5 && (this->target_))
-        {
             this->forgetTarget();
-        }
 
         // next enemy
         random = rnd(maxrand);
-//std::cout << "next enemy: " << random << std::endl;
         if (random < 10 && (this->target_))
-        {
             this->searchNewTarget();
-        }
 
         // fly somewhere
         random = rnd(maxrand);
-//std::cout << "fly somewhere: " << random << std::endl;
         if (random < 40 && (!this->bHasTargetPosition_ && !this->target_))
-        {
             this->searchNewTargetPosition();
-        }
 
         // stop flying
         random = rnd(maxrand);
-//std::cout << "stop flying: " << random << std::endl;
         if (random < 10 && (this->bHasTargetPosition_ && !this->target_))
-        {
             this->bHasTargetPosition_ = false;
-        }
 
         // fly somewhere else
         random = rnd(maxrand);
-//std::cout << "fly somewhere else: " << random << std::endl;
         if (random < 30 && (this->bHasTargetPosition_ && !this->target_))
-        {
             this->searchNewTargetPosition();
-        }
 
         // shoot
         random = rnd(maxrand);
-//std::cout << "shoot: " << random << std::endl;
         if (random < 75 && (this->target_ && !this->bShooting_))
-        {
             this->bShooting_ = true;
-        }
 
         // stop shooting
         random = rnd(maxrand);
-//std::cout << "stop shooting: " << random << std::endl;
         if (random < 25 && (this->bShooting_))
-        {
             this->bShooting_ = false;
-        }
+    }
+
+    void SpaceShipAI::damage(float damage)
+    {
+        this->health_ -= damage;
+        if (this->health_ <= 0)
+        {
+            this->kill();
+            SpaceShipAI::createEnemy(1);
+        }
+    }
+
+    void SpaceShipAI::kill()
+    {
+        ParticleSpawner* explosion = new ParticleSpawner("Orxonox/BigExplosion1part1", 3.0);
+        explosion->setPosition(this->getPosition());
+        explosion->getParticleInterface()->setKeepParticlesInLocalSpace(true);
+        explosion->setScale(4);
+        explosion->create();
+
+        explosion = new ParticleSpawner("Orxonox/BigExplosion1part2", 3.0);
+        explosion->setPosition(this->getPosition());
+        explosion->getParticleInterface()->setKeepParticlesInLocalSpace(true);
+        explosion->setScale(4);
+        explosion->create();
+
+        Vector3 ringdirection = Vector3(rnd(), rnd(), rnd());
+        ringdirection.normalise();
+        explosion = new ParticleSpawner("Orxonox/BigExplosion1part3", 3.0, 0.5, ringdirection);
+        explosion->setPosition(this->getPosition());
+        explosion->getParticleInterface()->setKeepParticlesInLocalSpace(true);
+        explosion->setScale(4);
+        explosion->create();
+
+        delete this;
     }
 
@@ -193,5 +214,5 @@
             this->moveToTargetPosition(dt);
 
-        if (this->bShooting_ && this->isCloseAtTarget(2000) && this->isLookingAtTarget(Ogre::Math::PI / 10.0f))
+        if (this->bShooting_ && this->isCloseAtTarget(2500) && this->isLookingAtTarget(Ogre::Math::PI / 10))
             this->doFire();
 
@@ -201,23 +222,21 @@
     void SpaceShipAI::moveToTargetPosition(float dt)
     {
-        static Radian RadianZERO(0);
-
-//        float dotprod = (this->getOrientation() * Ogre::Vector3::UNIT_X).dotProduct(this->targetPosition_ - this->getPosition());
-        Quaternion rotation = (this->getOrientation() * Ogre::Vector3::UNIT_X).getRotationTo(this->targetPosition_ - this->getPosition());
-/*
-std::cout << "scalprod: " << dotprod << std::endl;
-std::cout << "dist: " << this->targetPosition_ - this->getPosition() << std::endl;
-std::cout << "yaw: " << rotation.getYaw().valueRadians() << std::endl;
-std::cout << "pitch: " << rotation.getPitch().valueRadians() << std::endl;
-std::cout << "roll: " << rotation.getRoll().valueRadians() << std::endl;
-*/
-        this->setMoveYaw(-rotation.getRoll().valueRadians());
-        this->setMovePitch(rotation.getYaw().valueRadians());
-
-        if ((this->targetPosition_ - this->getPosition()).length() > 100)
-        {
+        Vector3 proj = Ogre::Plane(this->getDir(), this->getPosition()).projectVector(this->targetPosition_ - this->getPosition());
+        float angle = acos((this->getOrth().dotProduct(proj)) / (this->getOrth().length()*proj.length()));
+
+        if ((this->getDir().crossProduct(this->getOrth())).dotProduct(this->targetPosition_ - this->getPosition()) > 0)
+            this->setMoveYaw(sgn(sin(angle)));
+        else
+            this->setMoveYaw(-sgn(sin(angle)));
+        this->setMovePitch(sgn(cos(angle)));
+
+        if ((this->targetPosition_ - this->getPosition()).length() > 300)
             this->setMoveLongitudinal(1);
-        }
-
+
+        if (this->isCloseAtTarget(300) && this->target_)
+        {
+            if (this->getVelocity().length() > this->target_->getVelocity().length())
+                this->setMoveLongitudinal(-1);
+        }
     }
 
@@ -241,5 +260,5 @@
                 Vector3 distanceNew = it->getPosition() - this->getPosition();
                 if (!this->target_ || it->getPosition().squaredDistance(this->getPosition()) * (1.5f + acos((this->getOrientation() * Ogre::Vector3::UNIT_X).dotProduct(distanceNew) / speed / distanceNew.length()) / (2 * Ogre::Math::PI))
-                        < this->targetPosition_.squaredDistance(this->getPosition()) * (1.5f + acos((this->getOrientation() * Ogre::Vector3::UNIT_X).dotProduct(distanceCurrent) / speed / distanceCurrent.length()) / (2 * Ogre::Math::PI)))
+                        < this->targetPosition_.squaredDistance(this->getPosition()) * (1.5f + acos((this->getOrientation() * Ogre::Vector3::UNIT_X).dotProduct(distanceCurrent) / speed / distanceCurrent.length()) / (2 * Ogre::Math::PI)) + rnd(-250, 250))
                 {
                     this->target_ = (*it);
@@ -248,5 +267,5 @@
             }
         }
-   }
+    }
 
     void SpaceShipAI::forgetTarget()
@@ -260,5 +279,5 @@
         if (!this->target_)
             return;
-/*
+
         Vector3 enemymovement = this->target_->getVelocity();
         Vector3 distance_normalised = this->target_->getPosition() - this->getPosition();
@@ -267,4 +286,5 @@
         float scalarprod = enemymovement.dotProduct(distance_normalised);
         float aimoffset = scalarprod*scalarprod + Projectile::getSpeed() * Projectile::getSpeed() - this->target_->getVelocity().squaredLength();
+
         if (aimoffset < 0)
         {
@@ -273,21 +293,26 @@
         }
         aimoffset = -scalarprod + sqrt(aimoffset);
-        this->targetPosition_ = enemymovement + distance_normalised * aimoffset;
+        this->targetPosition_ = this->getPosition() + enemymovement + distance_normalised * aimoffset;
         this->bHasTargetPosition_ = true;
-
-        std::cout << "targetpos: " << this->targetPosition_ << std::endl;
-*/
-        this->targetPosition_ = this->target_->getPosition();
-        this->bHasTargetPosition_ = true;
     }
 
     bool SpaceShipAI::isCloseAtTarget(float distance)
     {
-        return (this->getPosition().squaredDistance(this->targetPosition_) < distance*distance);
+        if (!this->target_)
+            return (this->getPosition().squaredDistance(this->targetPosition_) < distance*distance);
+        else
+            return (this->getPosition().squaredDistance(this->target_->getPosition()) < distance*distance);
     }
 
     bool SpaceShipAI::isLookingAtTarget(float angle)
     {
-        return (this->getOrientation() * Ogre::Vector3::UNIT_X).directionEquals(this->targetPosition_ - this->getPosition(), Radian(angle));
+        Vector3 dist = this->targetPosition_ - this->getPosition();
+        return (acos((this->getDir().dotProduct(dist)) / (dist.length() * this->getDir().length())) < angle);
+    }
+
+    void SpaceShipAI::shipDied(SpaceShipAI* ship)
+    {
+        this->forgetTarget();
+        this->searchNewTargetPosition();
     }
 }
