Index: branches/adm/src/world_entities/npcs/adm_turret.cc
===================================================================
--- branches/adm/src/world_entities/npcs/adm_turret.cc	(revision 10680)
+++ branches/adm/src/world_entities/npcs/adm_turret.cc	(revision 10681)
@@ -67,4 +67,7 @@
 			.describe("The filename of the World Entity, that is to be shot at")
 			.defaultValues("");
+                
+                LoadParam(root, "type", this, AdmTurret, setType)
+                        .describe("floor|ceil"); 
 
 		LoadParamXML(root, "Cannons", this, AdmTurret, addCannons)
@@ -74,8 +77,14 @@
 
 	}
+//         this->removeNodeFlags( PNODE_ALL );
+//         this->addNodeFlags( PNODE_ROTATE_AND_MOVE );
         
-        //HACK this is really ugly because if you move the AdmTurret its cannons wont follow
-        if ( this->cannons )
-          this->cannons->setParent( NullParent::getNullParent() );
+        if ( this->isCeil )
+        {
+          Vector a = this->sensor->getRelCoor();
+          this->sensor->setRelCoor( -a.x, -a.y, -a.z );
+          a = this->cannons->getRelCoor();
+          this->cannons->setRelCoor( -a.x, -a.y, -a.z );
+        }
 }
 
@@ -96,9 +105,31 @@
 }
 
+void AdmTurret::setType( const std::string& type )
+{
+  if ( type == "floor" )
+  {
+    this->isCeil = false;
+    return;
+  }
+  
+  if ( type == "ceil" )
+  {
+    this->isCeil = true;
+    return;
+  }
+  
+  //invalid argument
+  PRINTF(1)("%s is not a valid type for AdmTurret\n", type.c_str());
+  assert("false");
+}
+
 void AdmTurret::init()
 {
 	this->registerObject(this, AdmTurret::_objectList);
         
-        //this->removeNodeFlags( 7 );
+        this->bodyAngle = this->cannonAngle = 0.0f;
+        this->isActive = true;
+        this->range = 400;
+        this->isCeil = false;
 }
 
@@ -112,5 +143,9 @@
 
   Vector playerPos = this->myTarget->getAbsCoor();
-  this->moveTowards( playerPos - ( this->cannons->getAbsCoor() ),  dt);
+  Vector ds = playerPos - ( this->cannons->getAbsCoor() );
+  if ( isActive && ds.len() <= range )
+    this->moveTowards( ds,  dt);
+  else
+    this->moveTowards( Vector(0, -1, 0), dt );
 }
 
@@ -216,76 +251,63 @@
 void AdmTurret::moveTowards( Vector targetDir, float dt )
 {
-#if 0
-  static Quaternion mrot = this->getAbsDir();
-  Quaternion ry( dt, Vector(0, 1, 0) );
-  mrot *= ry;
-  this->setAbsDir(mrot);
-
-  static Quaternion rot = this->cannons->getAbsDir();
-  Quaternion rx( dt, Vector( 0, 0, 1 ) );
-  rot *= rx;
-  this->cannons->setAbsDir(rot*mrot);
-  return;
-#endif
-
-
-
-
-  Quaternion cur = this->getAbsDir();
-  
-  Quaternion ry( dt, cur.inverse().apply( Vector( 0, 1, 0 ) ) );
-  
-  Quaternion tmp1 = cur * ry;
-  Quaternion tmp2 = cur * ry.inverse();
-  
-  bool usetmp1 = false;
-  Quaternion r1;
-  if ( tmp1.apply( Vector(1, 0, 0) ).dot(targetDir) < tmp2.apply( Vector(1, 0, 0)).dot(targetDir) )
+  if ( this->cannons->getParent() != NullParent::getNullParent() )
+    this->cannons->setParent( NullParent::getNullParent() );
+  
+  targetDir.normalize();
+  
+  float dAngle = dt;
+  
+  float bestResult = -1.0f;
+  Quaternion bestBodyRot;
+  Quaternion bestCannonRot;
+  float bestBodyAngle = 0.0f;
+  float bestCannonAngle = 0.0f;
+  
+//   Quaternion baseRot(0, Vector);
+//   if ( isCeil )
+//   {
+//     printf( "ceil\n" );
+//     baseRot = Quaternion( PI/2, Vector( 0, 0, 1 ) );
+//   }
+  
+  for ( int dBodyAngle = -1; dBodyAngle<2; dBodyAngle++ )
   {
-    usetmp1 = true;
-    cur = tmp1;
-    r1 = ry;
+    for ( int dCannonAngle = -1; dCannonAngle<2; dCannonAngle++ )
+    {
+      float bodyAngle = this->bodyAngle + dBodyAngle*dAngle;
+      float cannonAngle = this->cannonAngle + dCannonAngle*dAngle;
+      
+      while ( bodyAngle > 2*PI )
+        bodyAngle -= 2*PI;
+      while ( bodyAngle < 0 )
+        bodyAngle += 2*PI;
+      while ( cannonAngle > 2*PI )
+        cannonAngle -= 2*PI;
+      while ( cannonAngle < 0 )
+        cannonAngle += 2*PI;
+      
+      Quaternion bodyRot( bodyAngle, Vector( 0, 1, 0 ) );
+      Quaternion cannonRot( cannonAngle, Vector( 0, 0, 1) );
+      
+//       bodyRot = baseRot * bodyRot;
+//       cannonRot = baseRot * cannonRot;
+      
+      float result = (bodyRot * cannonRot).apply( Vector( -1, 0, 0 ) ).dot( targetDir );
+      
+      if ( result > bestResult )
+      {
+        bestResult = result;
+        bestBodyRot = bodyRot;
+        bestBodyAngle = bodyAngle;
+        bestCannonRot = cannonRot;
+        bestCannonAngle = cannonAngle;
+      }
+    }
   }
-  else
-  {
-    cur = tmp2;
-    r1 = ry.inverse();
-  }
-  
-  this->setAbsDir( cur );
-
-  
-  Quaternion cur2 = this->cannons->getAbsDir();
-  Quaternion rx( dt, cur.inverse().apply( Vector( 0, 0, 1 ) ) );
-  Quaternion rr( dt, cur2.inverse().apply( Vector( 0, 1, 0 ) ) );
-  if ( !usetmp1 )
-    rr = rr.inverse();
-  
-  
-  tmp1 = cur2 * rx;
-  tmp2 = cur2 * rx.inverse();
-
-  Quaternion dec;
-  Quaternion r2;
-  if ( tmp1.apply(  Vector(-1, 0, 0) ).dot(targetDir) > tmp2.apply( Vector(-1, 0, 0) ).dot(targetDir) )
-  {
-    r2 = rx;
-    dec = tmp1;
-  }
-  else
-  {
-    r2 = rx.inverse();
-    dec = tmp2;
-  }
-  
-  float dp = dec.apply( Vector(-1, 0, 0) ).dot(Vector(0, 1, 0));
-  if ( dp > -0.9 && dp < 0.9 )
-  {
-    cur2 = dec;
-  }
-
-  this->cannons->setAbsDir( cur2  );
-
-
-
-}
+  
+  this->bodyAngle = bestBodyAngle;
+  this->cannonAngle = bestCannonAngle;
+  
+  this->setAbsDir( bestBodyRot );
+  this->cannons->setAbsDir( bestBodyRot * bestCannonRot );
+}
Index: branches/adm/src/world_entities/npcs/adm_turret.h
===================================================================
--- branches/adm/src/world_entities/npcs/adm_turret.h	(revision 10680)
+++ branches/adm/src/world_entities/npcs/adm_turret.h	(revision 10681)
@@ -44,4 +44,13 @@
 
 		   void moveTowards( Vector targetDir, float dt );
+                   
+                   float bodyAngle;
+                   float cannonAngle;
+                   
+                   bool isActive;
+                   float range;
+                   
+                   bool isCeil;
+                   void setType( const std::string& type );
                                             
       };
