/* very simple to install, simply replace your do_who with mine */

/*
 * if you use this, please give me credit or at least
 * send me an email saying you are using this code. i
 * got a couple section from TAKA, creator of GhostMUD
 */

 /* FUNCTIONS: */
 /* separates IMMs from MORTs */
 /*    option for immtitle    */
 /*    option for whotitle    */
 /*   aligns correctly now    */
 /* if no mortals are online, wont add extra [================]*/
 /* if no immorts are online, wont add extra [================]*/
 


void do_who( CHAR_DATA *ch, char *argument )
{
    char buf[MAX_STRING_LENGTH], buf2[MAX_STRING_LENGTH], buf3[MAX_STRING_LENGTH], buf4[MAX_STRING_LENGTH], buf5[MAX_STRING_LENGTH];
    char buf6[MAX_STRING_LENGTH], buf7[MAX_STRING_LENGTH], buf8[MAX_STRING_LENGTH];
    BUFFER *output;
    DESCRIPTOR_DATA *d;
    int iClass, iRace, iClan, iLevelLower, iLevelUpper;
    int nNumber, nMatch, immmatch, mortmatch, wlevel;
    bool rgfClass[MAX_CLASS];
    bool rgfRace[MAX_PC_RACE];
    bool rgfClan[MAX_CLAN];
    bool fClassRestrict = FALSE;
    bool fClanRestrict = FALSE;
    bool fClan = FALSE;
    bool fRaceRestrict = FALSE;
    bool fImmortalOnly = FALSE;
    int half, sechalf;
	
/*
* Initalize Variables.
*/

    immmatch = 0;
	mortmatch = 0;
    nNumber = 0;
	nMatch = 0;
    buf[0] = '\0';
    output = new_buf();


    {
	sprintf (buf, "{R   F{rorsaken {RR{realms\n\r");
    send_to_char (buf, ch);
    }     
    
    
    /*
     * Set default arguments.
     */
    iLevelLower    = 0;
    iLevelUpper    = MAX_LEVEL;
    for ( iClass = 0; iClass < MAX_CLASS; iClass++ )
        rgfClass[iClass] = FALSE;
    for ( iRace = 0; iRace < MAX_PC_RACE; iRace++ )
        rgfRace[iRace] = FALSE;
    for (iClan = 0; iClan < MAX_CLAN; iClan++)
		rgfClan[iClan] = FALSE;

    /*
     * Parse arguments.
     */
    for ( ;; )
    {
        char arg[MAX_STRING_LENGTH];

        argument = one_argument( argument, arg );
        if ( arg[0] == '\0' )
            break;

        if ( is_number( arg ) )
        {
            switch ( ++nNumber )
            {
            case 1: iLevelLower = atoi( arg ); break;
            case 2: iLevelUpper = atoi( arg ); break;
            default:
                send_to_char( "Only two level numbers allowed.\n\r", ch );
                return;
            }
        }
        else
        {

            /*
             * Look for classes to turn on.
             */
            if ((!str_prefix(arg,"immortals")) || (!str_prefix(arg, "imm")))
            {
                fImmortalOnly = TRUE;
            }
            else
            {
                iClass = class_lookup(arg);
                if (iClass == -1)
                {
                    iRace = race_lookup(arg);

					if (iRace == 0 || iRace >= MAX_PC_RACE)
					{
						if (!str_prefix(arg,"clan"))
							fClan = TRUE;
						else
						{
							iClan = clan_lookup(arg);
							if (iClan)
							{
								fClanRestrict = TRUE;
							   	rgfClan[iClan] = TRUE;
							}
							else
							{
		                       	send_to_char("That's not a valid race, class, or clan.\n\r", ch);
                            	return;
							}
						}
					}
                    else
                    {
                        fRaceRestrict = TRUE;
                        rgfRace[iRace] = TRUE;
                    }
                }
                else
                {
                    fClassRestrict = TRUE;
                    rgfClass[iClass] = TRUE;
                }
            }
        }
    } // for

	/*
	 * Count and output the IMMs.
	 */
    sprintf( buf, "{W|{g==================={W|{x\n\r");
	add_buf(output,buf);
	sprintf( buf, "{W[{G I m m o r t a l s {W]{x\n\r");
	add_buf(output,buf);
    sprintf( buf, "{W|{g==================={W|{x\n\r");
	add_buf(output,buf);	

	for( wlevel=MAX_LEVEL; wlevel>LEVEL_HERO; wlevel-- )
	{
		for ( d = descriptor_list; d != NULL; d = d->next )
		{
		    CHAR_DATA *wch;
	        char const *class;

	        if ( d->connected != CON_PLAYING || !can_see( ch, d->character ) )
		        continue;

	        wch   = ( d->original != NULL ) ? d->original : d->character;

			if( wch->level != wlevel )
		 	 	continue;

			if (!can_see(ch,wch)  || wch->level < LEVEL_IMMORTAL)
				continue;


	        if ( wch->level < iLevelLower
			    ||   wch->level > iLevelUpper
		        || ( fImmortalOnly  && wch->level < LEVEL_IMMORTAL )
		        || ( fClassRestrict && !rgfClass[wch->class] )
		        || ( fRaceRestrict && !rgfRace[wch->race])
				|| ( fClan && !is_clan(wch))
				|| ( fClanRestrict && !rgfClan[wch->clan]))
		        continue;

	        immmatch++;
	        nMatch++;

	        /*
	         * Figure out what to print for class.
			 */
			class = class_table[wch->class].who_name;
			switch ( wch->level )
			{
			default: break;
	        {
			case MAX_LEVEL - 0 : class = "IMP";     break;
            case MAX_LEVEL - 1 : class = "CRE";     break;
            case MAX_LEVEL - 2 : class = "SUP";     break;
            case MAX_LEVEL - 3 : class = "DEI";     break;
            case MAX_LEVEL - 4 : class = "GOD";     break;
            case MAX_LEVEL - 5 : class = "IMM";     break;
            case MAX_LEVEL - 6 : class = "DEM";     break;
            case MAX_LEVEL - 7 : class = "ANG";     break;
            case MAX_LEVEL - 8 : class = "AVA";     break;
            case MAX_LEVEL - 9 : class = "BLD";		break;
	        }
			}

	if (IS_SET (wch->act, PLR_KILLER))
	{
		sprintf(buf6, "{R>{x");
	}
	if (!IS_SET (wch->act, PLR_KILLER))
	{
		sprintf(buf6, "{W>{x");
	}	

	if (IS_SET (wch->act, PLR_KILLER))
	{
		sprintf(buf7, "{R<{x");
	}
	if (!IS_SET (wch->act, PLR_KILLER))
	{
		sprintf(buf7, "{W<{x");
	}		
		
	sprintf(buf8, "%6s", wch->race < MAX_PC_RACE ? pc_race_table[wch->race].who_name : "     ");	
		
  if ((wch->level >= 101) && (wch->pcdata->immtitle != NULL))
  {
    if (colorstrlen(wch->pcdata->immtitle) == 19)
    {
      sprintf(buf3, "{W%s{x%s{W%s{x", buf6, wch->pcdata->immtitle, buf7);
    }
    else if (colorstrlen(wch->pcdata->immtitle) == 18)
    {
      sprintf(buf3, "{W%s{x%s{W %s{x", buf6, wch->pcdata->immtitle, buf7);
    }
    else
    {
      half = ((19 - colorstrlen(wch->pcdata->immtitle)) / 2);
      sechalf = (19 - (half + colorstrlen(wch->pcdata->immtitle)));
      sprintf(buf3, "{W%s{x%*c%s%*c{W%s{x", buf6, half, ' ', wch->pcdata->immtitle, sechalf, ' ', buf7);   
    }
  }
  else	
  {
  					sprintf( buf3, "{W%s {C%3d{G%6s {M%s  %s  {W%s", buf6, wch->level, buf8, class, wch->sex == 0 ? "{GN{x" : wch->sex == 1 ? "{RM{x" : "{MF{x", buf7);
    			}
	
  if ((wch->level > 0) && (wch->level < 111))
  {  					
  if ((wch->pcdata->cname != NULL))
  {
	sprintf(buf5, "{x%s{x", wch->pcdata->cname);
  }    			
  else
  {
    sprintf(buf5, "{W%s{x", wch->name);
  }
  }
      			
			/*
			 * Format it up.
			 */
			sprintf( buf, "%s %s %s%s%s{W%s{x%s\n\r",
		    	buf3, 
    			(is_clan(wch) || IS_SET(clan_table[wch->clan].flags,GUILD_INDEPENDENT)) ? clan_table[wch->clan].who_name : "           ",
				wch->incog_level >= LEVEL_HERO ? "{C({WI{W){x " : "",
				wch->invis_level >= LEVEL_HERO ? "{W({WW{W){x " : "",
				IS_SET(wch->comm, COMM_AFK) ? "{W[{RAFK{W]{X " : "",
				buf5,
				IS_NPC(wch) ? "" : wch->pcdata->title );
			add_buf(output,buf);
	}
}
	/*
	 * Count and output the Morts.
	 */	 
	 
	if (immmatch > 0)
	{ 
    sprintf( buf, "{W|{g==================={W|{x\n\r");
	add_buf(output,buf);
	}
	if (immmatch == 0)
	{
	}
	sprintf( buf, "{W[  {G M o r t a l s   {W]{x\n\r");
	add_buf(output,buf);
    sprintf( buf, "{W|{g==================={W|{x\n\r");
    add_buf(output,buf);
	
	for( wlevel=LEVEL_HERO; wlevel>0; wlevel-- )
	{
		for ( d = descriptor_list; d != NULL; d = d->next )
	    {
	        CHAR_DATA *wch;
	        char const *class;

	        if ( d->connected != CON_PLAYING || !can_see( ch, d->character ) )
	            continue;

	        wch   = ( d->original != NULL ) ? d->original : d->character;

			if( wch->level != wlevel )
			  	continue;

/*			if (!can_see(ch,wch) || wch->level > ch->level || wch->level > (MAX_LEVEL - 5))
			    continue; */
			if (!can_see(ch,wch))
			    continue;

			if ( wch->level < iLevelLower
		        ||   wch->level > iLevelUpper
		        || ( fImmortalOnly  && wch->level < LEVEL_IMMORTAL )
		        || ( fClassRestrict && !rgfClass[wch->class] )
				|| ( fRaceRestrict && !rgfRace[wch->race])
				|| ( fClan && !is_clan(wch))
				|| ( fClanRestrict && !rgfClan[wch->clan]))
			    continue;

			mortmatch++;
			nMatch++;
			
			/*
			 * Figure out what to print for class.
			 */
			class = class_table[wch->class].who_name;
			switch ( wch->level )
			{
			default: break;
            {
                case MAX_LEVEL - 50 : class = "{WHRO{x";     break;
            }
			}

  if ((wch->level <= 100) && (wch->pcdata->whotitle != NULL))
  {
    if (colorstrlen(wch->pcdata->whotitle) == 19)
    {
      sprintf(buf4, "{W>{x%s{W<{x", wch->pcdata->whotitle);
    }
    else if (colorstrlen(wch->pcdata->whotitle) == 18)
    {
      sprintf(buf4, "{W>{x%s{W <{x", wch->pcdata->whotitle);
    }
    else
    {
      half = ((19 - colorstrlen(wch->pcdata->whotitle)) / 2);
      sechalf = (19 - (half + colorstrlen(wch->pcdata->whotitle)));
      sprintf(buf4, "{W>{x%*c%s%*c{W<{x", half, ' ', wch->pcdata->whotitle, sechalf, ' ');   
    }
  }
  else	
  {
  	  sprintf( buf4, "{W> {C%3d{G%6s {M%s  %s  {W<", wch->level, buf8, class, wch->sex == 0 ? "{GN{x" : wch->sex == 1 ? "{RM{x" : "{MF{x");
  }			
			
  if ((wch->level > 0) && (wch->level < 111))
  {  					
  if ((wch->pcdata->cname != NULL))
  {
	sprintf(buf5, "{x%s{x", wch->pcdata->cname);
  }    			
  else
  {
    sprintf(buf5, "{W%s{x", wch->name);
  }
  }
			/*
			 * Format it up.
			 */
			sprintf( buf, "%s %s %s%s{x%s\n\r",
		    	buf4,
				(is_clan(wch) || IS_SET(clan_table[wch->clan].flags,GUILD_INDEPENDENT)) ? clan_table[wch->clan].who_name : "           ",
				IS_SET(wch->comm, COMM_AFK) ? "{W[{RAFK{W]{X " : "",
				buf5,
				IS_NPC(wch) ? "" : wch->pcdata->title );
			add_buf(output,buf);

		}
	}

    max_on = UMAX (nMatch, max_on);
    
    if (mortmatch > 0)
    {
    sprintf( buf, "{W|{g==================={W|{x\n\r");
	add_buf(output,buf);
	}
	if (mortmatch == 0)
	{
	}
	sprintf( buf2,
		"\n\r{G Total connected: {W%d{G\n\r", nMatch);
	add_buf(output,buf2);
	sprintf( buf2,
		"{G Immortals found: {W%d{G\n\r", immmatch);
	add_buf(output,buf2);
	sprintf( buf2,
		"{G   Mortals found: {W%d\n\r", mortmatch);
	add_buf(output,buf2);
	sprintf( buf2,
		"{GMost found today: {M%d{x\n\r", max_on );
	add_buf(output,buf2);
	page_to_char( buf_string(output), ch );
	free_buf(output);
	return;

}


/* removes {x from strlen */
int colorstrlen(char *argument)
{
  char *str;
  int strlength;

  if (argument == NULL || argument[0] == '\0')
    return 0;

  strlength = 0;
  str = argument;

  while (*str != '\0')
  {
    if ( *str != '{' ) 
    {					
      str++;
      strlength++;
      continue;
    }

    if (*(++str) == '{') 
      strlength++;

    str++;
  }
  return strlength;
}