How to call Shortcode categories for custom post types?

What surprise me is that someone on May 2013, write a tutorial using extract and query_posts in same function.

extract is considered a bad practice in PHP in general, and it’s usage was abandoned also from WP core (it will no longer be used, but there are still extract calls in actual code).

query_posts is a bad practice in WordPress world, you can read about it in the most famous WPSE answer by Rarst and in Codex too (that actually use the picture by Rarst).

Also:

  1. your code use the deprecarted argument ‘numposts’, use ‘posts_per_page’ instead
  2. your code put stuff in html output without escaping with esc_* functions
  3. your code output images without alt attribute that is required for W3C compliant html code

That said, what you want to do is simple a matter of a new WP_Query called from shortcode callback.

function nivo_slider_function( $atts ){

   $posts_per_page = isset( $atts['posts'] ) ? $atts['posts'] : -1;

   $args = array(
     'posts_per_page' => $posts_per_page,
     'orderby' => 'menu_order',
     'order' => 'ASC',
     'post_type' => 'homepage_slider'
   );

   if ( isset($atts['category']) && ! empty( $atts['category'] ) ) {
     $args['category_name'] = $atts['category'];
   }

   $query = new WP_Query( $args );

   // nothing to do if we have no posts
   if ( ! $query->have_posts() ) return;

   $slide_format="<a href="https://wordpress.stackexchange.com/questions/138940/%s" rel="nofollow"><img src="https://wordpress.stackexchange.com/questions/138940/%s" alt="" /></a>";
   $slides="";
   $slider="";

   while( $query->have_posts() ) { $query->the_post();
     $thumbid = get_post_thumbnail_id($post->ID);
     // if post has not thumbnail return
     if ( empty( $thumbid ) ) continue;
     $img_src = (array) wp_get_attachment_image_src( $thumbid, 'homepage-slide' );
     // if a valid image is not foud return
     if ( empty( $img_src ) || ! filter_var( $img_src[0], FILTER_VALIDATE_URL ) ) continue;
     $target_link = get_post_meta( get_the_ID(), 'slide_target_link', true );
     // if no valid link is saved in 'slide_target_link' meta, set link to '#'
     if (empty( $target_link ) || ! filter_var( $target_link, FILTER_VALIDATE_URL ) ) {
       $target_link = '#';
     }
     $slides .= sprintf( $slide_format, esc_url( $target_link ), esc_url( $img_src[0] ) );
   }

   wp_reset_postdata();

   if ( ! empty( $slides ) ) {
     $id = esc_attr( wp_generate_password( 6, false, false) );
     $slider = "<div id=\"slider_{$id}\" class=\"nivoSlider\">{$slides}</div>";
   }

   return $slider;
}