Here's a couple more things you may want to correct before re-uploading the attachment.
Although you clean the groupid variable at the memberlist_start hook, you never use that version, instead you redeclare $groupid later on, using the unclean version.
At memberlist_start
Code:
$groupid = $vbulletin->input->clean_gpc('r', 'groupid', TYPE_UINT);
At memberlist_query_userscount
Code:
if (intval($_REQUEST['groupid']) > 0)
{
$groupid = intval($_REQUEST['groupid']);
$condition .= ' AND (FIND_IN_SET(\''.$groupid.'\', membergroupids) OR user.usergroupid = '.$groupid.')';
}
That final part should be:
Code:
if (intval($groupid) > 0)
{
$condition .= ' AND (FIND_IN_SET(\''.$groupid.'\', membergroupids) OR user.usergroupid = '.$groupid.')';
}
Also, although the $do_not_include variable hides the defined usergroups from the options list, members can still randomly try numbers and pull the memberlist for all those usergroups, regardless of the $do_not_include setting (apart from usergroups that are set in the AdminCP to be hidden from the memberlist).
If you move the $do_not_include declaration to the top of the plugin, it can also be checked when you check if $groupid > 0.