bool SoulDestroyer::SearchForRetreatPosition()
{
    WorldObjectId targetId = g_app->m_location->m_entityGrid->GetBestEnemy( m_pos.x, m_pos.z, 0.0, SOULDESTROYER_MAXSEARCHRANGE, m_id.GetTeamId() );
    
    if( targetId.IsValid() )
    {
        WorldObject *obj = g_app->m_location->GetEntity( targetId );
        AppDebugAssert( obj );

        double distance = 50.0;
        Vector3 retreatVector = ( m_pos - obj->m_pos ).Normalise();
        double angle = syncsfrand( M_PI * 1.0 );
        retreatVector.RotateAroundY( angle );
        m_targetPos = m_pos + retreatVector * distance;
        m_targetPos.y = min( m_targetPos.y, 300.0 );
        return true;
    }
     
    return false;
}
void LocationEditor::AdvanceModeBuilding()
{
	BuildingEditWindow *ew = (BuildingEditWindow *)EclGetWindow("editor_buildingid");
	if (ew && EclMouseInWindow(ew))	return;
	
	Camera *cam = g_app->m_camera;

	// Find the ID of the building the user is clicking on
	int newSelectionId = -1;
	if ( g_inputManager->controlEvent( ControlTileSelect ) )
	{
		Vector3 rayStart, rayDir;
		cam->GetClickRay( g_target->X(), g_target->Y(), &rayStart, &rayDir );
		newSelectionId = DoesRayHitBuilding(rayStart, rayDir);
	}

	if (m_selectionId == -1)
	{
		// If there isn't currently any selection, then check for a new one
		if (newSelectionId != -1)
		{
			m_selectionId = newSelectionId;
			BuildingsCreateWindow *cw = (BuildingsCreateWindow*)EclGetWindow("editor_buildings");
			AppDebugAssert(!ew);
			AppDebugAssert(cw);
			BuildingEditWindow *bew = new BuildingEditWindow("editor_buildingid");
			bew->m_w = cw->m_w;
			bew->m_h = 140;
			bew->m_x = cw->m_x;
			EclRegisterWindow(bew);
			bew->m_y = cw->m_y - bew->m_h - 10;
			m_waitingForRelease = true;

            Location *location = g_app->m_location;
		    Building *building = location->GetBuilding(m_selectionId);            
            if( building->m_type == Building::TypeTree )
            {
                TreeWindow *tw = new TreeWindow( "editor_treeditor" );
                tw->m_w = cw->m_w;
                tw->m_h = 230;
                tw->m_y = bew->m_y - tw->m_h - 10;
                tw->m_x = bew->m_x;
                EclRegisterWindow( tw );
            }
		}
	}
	else 
	{
		Location *location = g_app->m_location;
		Building *building = location->GetBuilding(m_selectionId);
	
		
		if ( g_inputManager->controlEvent( ControlTileSelect ) )                  // If left mouse is clicked then consider creating a new link
		{
			if (newSelectionId == -1)
			{
				EclRemoveWindow("editor_buildingid");
				m_selectionId = -1;
			}
			else if (m_tool == ToolLink)
			{
				building->SetBuildingLink(newSelectionId);
				m_tool = ToolNone;
			}
		}		
		else if ( g_inputManager->controlEvent( ControlTileDrag ) && newSelectionId == -1 )  // Otherwise consider rotation and movement
		{
			switch (m_tool)
			{
				case ToolMove:
				{
					Vector3 mousePos = g_app->m_userInput->GetMousePos3d();
					building->m_pos = mousePos;
					break;
				}
				case ToolRotate:
				{
					Vector3 front = building->m_front;
					front.RotateAroundY((float)g_target->dX() * 0.01);
					building->m_front = front;
					break;
				}
			}
		}
	}
}
void Nuke::Render( double _predictionTime )
{
    if( m_renderMarker )
    {
        RenderGroundMarker();
    }
    RenderSub( _predictionTime );
    if( m_exploded )
    {
        //RenderDeaths();
    }
    else
    {
        if( !m_launched ) return;

        Vector3 front = m_front;
        front.RotateAroundY( M_PI / 2.0f );
        Vector3 predictedPos = m_pos + m_vel * _predictionTime;;
        Vector3 entityUp = m_front;
        Vector3 entityRight (front ^ entityUp);

        Vector3 lengthVector = m_vel;
        lengthVector.SetLength( 10.0f );
        Vector3 fromPos = predictedPos;
        Vector3 toPos = predictedPos - lengthVector;

        Vector3 midPoint        = fromPos + (toPos - fromPos)/2.0f;
        Vector3 camToMidPoint   = g_app->m_camera->GetPos() - midPoint;
        float   camDistSqd      = camToMidPoint.MagSquared();
        Vector3 rightAngle      = (camToMidPoint ^ ( midPoint - toPos )).Normalise();

        entityRight = rightAngle;

        float size = 10.0f;  
        size *= (1.0f + 0.03f * (( m_id.GetIndex() * m_id.GetUniqueId() ) % 10));
        entityRight *= size;
        entityUp *= size * 2.0f;

        glDepthMask     ( false );
        glEnable        ( GL_BLEND );
        glBlendFunc     ( GL_SRC_ALPHA, GL_ONE );
        glEnable        ( GL_TEXTURE_2D );
        glBindTexture( GL_TEXTURE_2D, g_app->m_resource->GetTexture( "sprites/nuke.bmp" ) );

        RGBAColour colour = g_app->m_location->m_teams[m_id.GetTeamId()]->m_colour;
        if( m_id.GetTeamId() == g_app->m_location->GetMonsterTeamId() )
        {
            glBlendFunc     ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_COLOR );
            colour.Set( 255, 255, 255, 0 );
        }
        glColor4ubv(colour.GetData());

        glBegin(GL_QUADS);
            glTexCoord2i(0, 1);     glVertex3dv( (predictedPos - entityRight + entityUp).GetData() );
            glTexCoord2i(1, 1);     glVertex3dv( (predictedPos + entityRight + entityUp).GetData() );
            glTexCoord2i(1, 0);     glVertex3dv( (predictedPos + entityRight).GetData() );
            glTexCoord2i(0, 0);     glVertex3dv( (predictedPos - entityRight).GetData() );
        glEnd();

        RenderHistory( _predictionTime );

        glShadeModel    ( GL_FLAT );
        glDisable       ( GL_TEXTURE_2D );
        glDepthMask     ( true );
    }
}