/*****************************************************************************
 *  Group Replacement by Orion Elder.                                        *
 *                                                                           *
 *  Updates to this snippet can be found at the SSWRA:                       *
 *  http://www.geocities.com/knytehawk/smaug/index.html                      *
 *                                                                           *
 *  Please send all bug reports, suggestions, or ideas to:                   *
 *  orion_elder@charter.net                                                  *
 *                                                                           *
 *  NOTE: If you downloaded this snippet from the SSWRA disregard. I will    *
 *        under no circumstances support versions of this snippet gleaned    *
 *        from other sources. If you're having problems download a fresh     *
 *        copy from the SSWRA and re-install.                                *
 *                                                                           *
 * If you're having problems with your copy of this snippet, please check to *
 * ensure that no updates have been posted before seeking help.              *
 *                                                                           *
 * Copyright 2001-2009 by Orion Elder                                        *
 *****************************************************************************/

[act_comm.c]

Find do_group and replace it with the below:

/*
 * Overhauled 06/24/2001 to solve many of the bad issues in the code,
 * such as numerical level checks (gch->level < 50), etc. It is
 * mostly a change to the way the do_group display looks, but some
 * changes have been made to the grouping code to weed out potential
 * bugs. I also commented it all to hell, for those who might need to
 * work on it, for any reason. -Orion Elder
 *
 * Previous aesthetic updates by Blodkai. Other work by Haus, Scryn,
 * and possibly others.
 */
void do_group( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH];
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    /*
     * To change the maximum level difference for a group, adjust
     * this number. -Orion
     */
    int MAX_GROUP_LEVEL_DIFF = 9;

    one_argument( argument, arg );

    /*
     * If no argument is given, then show group information -Orion
     */
    if ( arg[0] == '\0' )
    {
	CHAR_DATA *gch;
	CHAR_DATA *leader = ch->leader ? ch->leader : ch;

        set_char_color( AT_DGREEN, ch );

	/*
	 * Display the headers for information. -Orion
	 */
        ch_printf( ch, "\n\rFollowing %-16.16s [class] [-race-] [hit] [mag] [mvs] [mst]%s\n\r",
	    PERS(leader, ch),
	    ch->level < LEVEL_AVATAR ? " [--level--]" : "" );

	/* Loop through characters checking for those in your group -Orion */
	for ( gch = first_char; gch; gch = gch->next )
	{
	    /*
	     * See if gch (the char being checked) is in ch's (the command
	     * issuer) group. If so, then proceed through.
	     */
	    if ( is_same_group( gch, ch ) )
	    {
		set_char_color( AT_DGREEN, ch );

		/*
		 * If affected by possess tell only name and level -Orion
		 */
		if ( IS_AFFECTED( gch, AFF_POSSESS ) )
		{
		    ch_printf( ch, "[%-3d] %s\n\r", gch->level,
			capitalize( PERS(gch, ch) ) );
		}
		/*
		 * Print off all that nifty information about gch to the
		 * ch. -Orion
		 */
		else
		{
		    /*
		     * Percentage variables, for displaying the percentage of
		     * hp/magic/moves to character. -Orion
		     */
		    int hp_perc, mg_perc, mv_perc;
		    double hp_temp, mg_temp, mv_temp;
		    double min, max;

		    /*
		     * Initialize the variables. -Orion
		     */
		    hp_perc = mg_perc = mv_perc = 0;
		    hp_temp = mg_temp = mv_temp = 0.0;
		    min = max = 0.0;

		    /*
		     * Calculate HP into a percentage. -Orion
		     */
		    min = (double) gch->hit;
		    max = (double) gch->max_hit;
		    hp_temp = (double) ( min/max );
		    hp_perc = (int) ( hp_temp * 100 );

		    /*
		     * Check for blood/mana then make it a percentage. -Orion
		     */
		    if ( IS_VAMPIRE( gch ) )
		    {
			min = (double) gch->pcdata->condition[COND_BLOODTHIRST];
			max = (double) ( gch->level + 10 );
			mg_temp = (double) ( min/max );
			mg_perc = (int) ( mg_temp * 100 );
		    }
		    else
		    {
			min = (double) gch->mana;
			max = (double) gch->max_mana;
			mg_temp = (double) ( min/max );
			mg_perc = (int) ( mg_temp * 100 );
		    }

		    /*
		     * Calculate Moves into a percentage. -Orion
		     */
		    min = (double) gch->move;
		    max = (double) gch->max_move;
		    mv_temp = (double) ( min/max );
		    mv_perc = (int) ( mv_temp * 100 );

		    /*
		     * Show a symbol based on alignment. -Orion
		     */
                    if ( IS_GOOD( gch ) )
			sprintf(buf, "+");
                    else if ( IS_NEUTRAL( gch ) )
			sprintf(buf, "o");
                    else if ( IS_EVIL( gch ) )
			sprintf(buf, "-");
                    else
			sprintf(buf, "X");

		    set_char_color( AT_DGREEN, ch );
		    send_to_char( "[", ch );

		    set_char_color( AT_GREEN, ch );
		    ch_printf( ch, "%-3d (", gch->level );

		    /*
		     * Display align color based on alignment. -Orion
		     */
		    if ( IS_GOOD( gch ) )
			set_char_color( AT_WHITE, ch );
		    else if ( IS_NEUTRAL( gch ) )
			set_char_color( AT_GREY, ch );
		    else if ( IS_EVIL( gch ) )
			set_char_color( AT_DGREY, ch );
		    else
			set_char_color( AT_YELLOW, ch );
		    ch_printf( ch, "%1.1s", buf );

		    set_char_color( AT_GREEN, ch );
		    send_to_char( ")", ch );

		    set_char_color( AT_DGREEN, ch );
		    send_to_char( "] ", ch );

		    set_char_color( AT_GREEN, ch );
		    ch_printf( ch, "%-16.16s ",
			capitalize( PERS( gch, ch ) ) );

		    ch_printf( ch, "%7.7s ", 
			class_table[gch->class]->who_name );

		    ch_printf( ch, "%8.8s ",
			race_table[gch->race]->race_name );

		    /*
		     * Display HP color based on danger level. -Orion
		     */
		    if ( hp_perc <= 33 )
			set_char_color( AT_DANGER, ch );
		    else if ( hp_perc <= 66 )
			set_char_color( AT_YELLOW, ch );
		    else
			set_char_color( AT_GREY, ch );
		    ch_printf( ch, "%4d%% ", hp_perc );

		    /*
		     * Display magic color based on blood/mana. -Orion
		     */
		    if ( IS_VAMPIRE(gch) )
			set_char_color( AT_BLOOD, ch );
		    else
			set_char_color( AT_LBLUE, ch );
		    ch_printf( ch, "%4d%% ", mg_perc );

		    /*
		     * Display move color based on danger level. -Orion
		     */
		    if ( mv_perc <= 33 )
			set_char_color( AT_DANGER, ch );
		    else if ( mv_perc <= 66 )
			set_char_color( AT_YELLOW, ch );
		    else
			set_char_color( AT_GREY, ch );
		    ch_printf( ch, "%4d%% ", mv_perc );

		    /*
		     * Display mental state color based on danger
		     * level. -Orion 
		     */
		    if ( gch->mental_state < -66
		      || gch->mental_state > 66 )
			set_char_color( AT_DANGER, ch );
		    else if ( gch->mental_state < -33
			   || gch->mental_state > 33 )
			set_char_color( AT_YELLOW, ch );
		    else
			set_char_color( AT_GREEN, ch );
		    ch_printf( ch, "%4.4s  ",
			gch->mental_state > 75  ? "+++" :
			gch->mental_state > 50  ? "=++" :
			gch->mental_state > 25  ? "==+" :
			gch->mental_state > -25 ? "===" :
			gch->mental_state > -50 ? "-==" :
			gch->mental_state > -75 ? "--=" : "---" );

		    set_char_color( AT_GREEN, ch );
		    if ( gch->level < LEVEL_AVATAR )
		    {
			ch_printf( ch, "%11d ",
			    exp_level( gch, gch->level+1) - gch->exp );
		    }
		    send_to_char( "\n\r", ch);
		}
	    }
	}
	return;
    }

    /*
     * Check if they are chose to disband the group, if so continue
     * through the function. -Orion
     */
    if ( !strcmp( arg, "disband" ))
    {
	CHAR_DATA *gch;
	int count = 0;

	/*
	 * Is the function caller the leader or master? If not, they
	 * don't HAVE this option. -Orion
	 */
	if ( ch->leader || ch->master )
	{
	    send_to_char( "You cannot disband a group if you're following someone.\n\r", ch );
	    return;
	}
	
	/*
	 * Loop through characters, removing them from the group if they are
	 * in it. -Orion
	 */
	for ( gch = first_char; gch; gch = gch->next )
	{
	    if ( is_same_group( ch, gch )
	    && ( ch != gch ) )
	    {
		/*
		 * If their leader isn't the person disbanding the group,
		 * then doing this is bad. -Orion
		 */
		if ( gch->leader )
		{
		    if ( gch->leader == ch )
			gch->leader = NULL;
		    else
			bug( "do_group: disbanding non-grouped member" );
		}
		/*
		 * Same as above. Better safe than sorry. -Orion
		 */
		if ( gch->master )
		{
		    if ( gch->master == ch )
			gch->master = NULL;
		    else
			bug( "do_group: disbanding non-grouped member" );
		}
		count++;
		send_to_char( "Your group is disbanded.\n\r", gch );
	    }
	}

	/*
	 * If count is equal to zero, they had no group members. - Orion
	 */
	if ( count == 0 )
	    send_to_char( "You have no group members to disband.\n\r", ch );
	else
	    send_to_char( "You disband your group.\n\r", ch );
	
	return;
    }

    /*
     * Check to see if they chose to group all, if so continue through
     * the function. -Orion
     */
    if ( !strcmp( arg, "all" ) )
    {
	CHAR_DATA *rch;
	int count = 0;

	/*
	 * Loop through characters in the room, adding elligible members to
	 * the caller's group. -Orion
	 */
	for ( rch = ch->in_room->first_person; rch; rch = rch->next_in_room )
	{
	    if ( ch != rch
	      && !IS_NPC( rch )
	      && can_see( ch, rch )
	      && rch->master == ch
	      && !ch->master
	      && !ch->leader
	      && abs( ch->level - rch->level ) < MAX_GROUP_LEVEL_DIFF
	      && !is_same_group( rch, ch )
	      && IS_PKILL( ch ) == IS_PKILL( rch ) )
	    {
		rch->leader = ch;
		count++;
	    }
	}
	
	/*
	 * If count is zero, then let them know they could not add anyone
	 * to their group, else let them know they did. -Orion
	 */
	if ( count == 0 )
	    send_to_char( "You have no eligible group members.\n\r", ch );
	else
	{
	    act( AT_ACTION, "$n groups $s followers.", ch, NULL, NULL,
		TO_ROOM );
	    send_to_char( "You group your followers.\n\r", ch );
	}
	return;
    }

    /*
     * If victim is NULL then the victim isn't in the room with the caller,
     * so let them know that. -Orion
     */
    if ( ( victim = get_char_room( ch, arg ) ) == NULL )
    {
	send_to_char( "They aren't here.\n\r", ch );
	return;
    }

    /*
     * Let them know that they can not group people when they are
     * following someone. -Orion
     */
    if ( ch->master || ( ch->leader && ch->leader != ch ) )
    {
	send_to_char( "But you are following someone else!\n\r", ch );
	return;
    }

    /*
     * Lets them know they can not group someone who is not following
     * them. -Orion
     */
    if ( victim->master != ch && ch != victim )
    {
	act( AT_PLAIN, "$N isn't following you.", ch, NULL, victim, TO_CHAR );
	return;
    }

    /*
     * Let them know that grouping themself is a no-no. -Orion
     */
    if ( victim == ch )
    {
	act( AT_PLAIN, "You can't group yourself.", ch, NULL, victim, TO_CHAR );
	return;
    }

    /*
     * If they're already in the group, remove them. -Orion
     */
    if ( is_same_group( victim, ch ) && ch != victim )
    {
	/*
	 * If the victim's leader isn't ch, then setting it to null is
	 * bad. -Orion
	 */
	if ( victim->leader )
	{
	    if ( victim->leader == ch )
		victim->leader = NULL;
	    else
		bug( "do_group: removing non-grouped member." );
	}

	act( AT_ACTION, "$n removes $N from $s group.",   ch, NULL, victim, TO_NOTVICT );
	act( AT_ACTION, "$n removes you from $s group.",  ch, NULL, victim, TO_VICT    );
	act( AT_ACTION, "You remove $N from your group.", ch, NULL, victim, TO_CHAR    );
	return;
    }

    /*
     * Check their level and pkill status to see if joining the group is a
     * viable option. If not, tell the involved parties so. -Orion
     */
    if ( abs( ch->level - victim->level ) >= MAX_GROUP_LEVEL_DIFF
    || ( IS_PKILL( ch ) != IS_PKILL( victim ) ) )
    {
	act( AT_PLAIN, "$N cannot join $n's group.",     ch, NULL, victim, TO_NOTVICT );
	act( AT_PLAIN, "You cannot join $n's group.",    ch, NULL, victim, TO_VICT    );
	act( AT_PLAIN, "$N cannot join your group.",     ch, NULL, victim, TO_CHAR    );
	return;
    }

    /*
     * Go ahead and group them. -Orion
     */
    victim->leader = ch;
    act( AT_ACTION, "$N joins $n's group.", ch, NULL, victim, TO_NOTVICT);
    act( AT_ACTION, "You join $n's group.", ch, NULL, victim, TO_VICT    );
    act( AT_ACTION, "$N joins your group.", ch, NULL, victim, TO_CHAR    );
    return;
}

Once you have replaced it, do a make, and you're done installing
this snippet. YAY!
