Who List (Immortal) BUG for EmberMUD
                             Fix Sheet by Rindar
            

The Bug: If there is only one immortal on, there is a bug that will
allow players to know that one imm is player.. even if the imm is 
Wizinvis.  When a player does a WHO and only one imm is on, the  
"Visible Immortals" header will still appear.. even if that one IMM
is Wizinvis.  So much for privacy, eh?

The Check:  Make sure all of the imms on are wizinvis, and then have   
a test mortal do a WHO.  If that mortal can see the "Visible Immortals"
header, you have the bug.

The Bugfix:  Because I didn't code this and the person that did doesn't
remember exactly what was done, I've decided not to write up an in-depth
install for this piece of code.  It is included at the bottom of this 
sheet, and can be popped in over the other do_who function in act_info.c.
If you don't want to insert it completely (only the fix), do a file 
compare with the original EmberMUD code to see what was changed.

        1)  Open act_info.c
        2)  Find the function "void do_who"
        3)  Delete it.
        3)  Replace it with the function at the bottom of the sheet. 
        4)  Recompile.  You are done.


-= Rindar
clogar@concentric.net


** Note:  This function is provided "as is" and may be used so long as 
1)  The author's name is kept at the top of the function (if requested) and
2)  all other previous licensing aggreements are abided by.  The author 
assumes no responsibility for problems that occur through use or install-
ation, including lost wages, bugs, deletions, downtimes, etc...  Use at 
your own risk.  All new code is copyrighted by its author.


New do_who function (act_info.c):

void do_who( CHAR_DATA *ch, char *argument )
{
      char arg[MAX_INPUT_LENGTH];
   char buf[MAX_STRING_LENGTH];
   
   char buf2[MAX_STRING_LENGTH];
    char output[4 * MAX_STRING_LENGTH];
    DESCRIPTOR_DATA *d;
    CHAR_DATA *who_list[300];
    int iClass;
    int iRace;
    int iLevelLower;
    int iLevelUpper;
    int nNumber;
    int nMatch;
    int length;
    int maxlength;
    int count;
    bool rgfClass[MAX_CLASS];
    bool rgfRace[MAX_PC_RACE];
    bool fClassRestrict;
    bool fRaceRestrict;
    bool fImmortalOnly;
    bool doneimmort=FALSE;
    bool donemort=FALSE;

    /*
     * Set default arguments.
     */
    iLevelLower    = 0;
    iLevelUpper    = MAX_LEVEL+2;
    fClassRestrict = FALSE;
    fRaceRestrict = FALSE;
    fImmortalOnly  = FALSE;
    for ( iClass = 0; iClass < MAX_CLASS; iClass++ )
        rgfClass[iClass] = FALSE;
    for ( iRace = 0; iRace < MAX_PC_RACE; iRace++ )
        rgfRace[iRace] = FALSE;

    /*
     * Parse arguments.
     */
    nNumber = 0;
    for ( ;; )
    {
        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 ( argument == "imm" )
            {
                fImmortalOnly = TRUE;
            }
            else
            {
                iClass = class_lookup(arg);
                if (iClass == -1)
                {
                    iRace = race_lookup(arg);

                    if (iRace == 0 || iRace >= MAX_PC_RACE)
                    {
                        do_whoname(ch, arg);
                        return;
                    }
                    else
                    {
                        fRaceRestrict = TRUE;
                        rgfRace[iRace] = TRUE;
                    }
                }
                else
                {
                    fClassRestrict = TRUE;
                    rgfClass[iClass] = TRUE;
                }
            }
        }
    }
    
    length=0;
    for ( d = descriptor_list ; d ; d = d->next ) {
        if ( (d->connected == CON_PLAYING) || (d->connected == CON_NOTE_TO) ||
        (d->connected == CON_NOTE_SUBJECT) || (d->connected == CON_NOTE_EXPIRE)
        || (d->connected == CON_NOTE_TEXT) || (d->connected == CON_NOTE_FINISH)) {
            insert_sort(who_list, d->character, length);
            length++;
        }
    }

    maxlength=length;

    /*
     * Now show matching chars.
     */
    nMatch = 0;
    buf[0] = '\0';
    output[0] = '\0';
    for ( length=0 ; length < maxlength ; length++ )
    {
        char const *class;

        /*
         * Check for match against restrictions.
         * Don't use trust as that exposes trusted mortals.
         */
        if ( who_list[length]->level > MAX_LEVEL-10
        &&   can_see( ch, who_list[length] )    
        &&   doneimmort==FALSE )
        { 
                sprintf( buf, "`K[`RVisible Immortals`K]\n\r\n\r");
                doneimmort=TRUE;
                strcat( output, buf );
        } 
        else if ( ( who_list[length]->level <= MAX_LEVEL-10 ) && donemort == FALSE) 
        {
           if ( doneimmort == TRUE ) 
           {
              sprintf( buf, "\n\r");
              strcat( output, buf);
           }
           sprintf( buf, "`K[`RVisible Mortals`K]\n\r\n\r");
           donemort = TRUE;
           strcat( output, buf );
        }
        if (/*who_list[length]->desc->connected != CON_PLAYING ||*/ !can_see( ch, who_list[length] ) )
            continue;

        if ( who_list[length]->level < iLevelLower
        ||   who_list[length]->level > iLevelUpper
        || ( fImmortalOnly  && who_list[length]->level < LEVEL_HERO )
        || ( fClassRestrict && !rgfClass[who_list[length]->class] ) 
        || ( fRaceRestrict && !rgfRace[who_list[length]->race]))
            continue;

        nMatch++;

        /*
         * Figure out what to print for class.
         */

        class = class_table[who_list[length]->class].who_name;
        switch ( who_list[length]->level )
        {
        default: break;
            {
                case MAX_LEVEL + 2 : class = "IMP";     break;
                case MAX_LEVEL + 1 : class = "IMP";     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;
            }
        }
       
        /*
         * Format it up.
         */
       sprintf( buf, "`K[`W%3d `Y%s `G%s`K] %s%s%s%s%s%s%s`w%s%s\n\r",
               (who_list[length]->level> MAX_LEVEL ? 100 : who_list[length]->level),
               who_list[length]->race < MAX_PC_RACE ? pc_race_table[who_list[length]->race].who_name 
               : "     ",
               class,
/*             IS_NPC(who_list[length]) ? 
 *             (who_list[length]->pIndexData->clan == 0) ? "" : "`W[`w" :
 *             (who_list[length]->pcdata->clan ==0) ? "" : "`W[`w",
 *             IS_NPC(who_list[length]) ? vis_clan(who_list[length]->pIndexData->clan)
 *             : vis_clan(who_list[length]->pcdata->clan),
 *             IS_NPC(who_list[length]) ? 
 *             (who_list[length]->pIndexData->clan == 0) ? "" : "`W]`w " :
 *             (who_list[length]->pcdata->clan ==0) ? "" : "`W]`w ", */
               "","","",
               IS_SET(who_list[length]->act, PLR_WIZINVIS) ? "`B(Wizi)`w " : "",
               IS_SET(who_list[length]->act, PLR_AFK) ? "`W(AFK) " : "",
               IS_SET(who_list[length]->act, PLR_KILLER) ? "`R(PK) " : "",
               IS_SET(who_list[length]->act, PLR_THIEF)  ? "`K(THIEF) "  : "",
               who_list[length]->name,
               IS_NPC(who_list[length]) ? "" : who_list[length]->pcdata->title);
       
       strcat(output, buf);
    }
   
   sprintf( buf2, "\n\r`wVisible Players Shown: `W%d\n\r`w", nMatch );
   strcat(output,buf2);
   count=0;
   for ( d = descriptor_list ; d ; d = d->next ) {
       if ( d->connected == CON_PLAYING 
           && !(IS_SET(d->character->act, PLR_WIZINVIS) ) ) 
         {
            count++;
         }
       else if ( ((d->connected == CON_PLAYING) || (d->connected == CON_NOTE_TO) ||
        (d->connected == CON_NOTE_SUBJECT) || (d->connected == CON_NOTE_EXPIRE)
        || (d->connected == CON_NOTE_TEXT) || (d->connected == CON_NOTE_FINISH))
                && !(d->character->invis_level > ch->level) )
         
         { count++; }
       
    }
   
   sprintf( buf2, "`wTotal Players Online: `W%d\n\r`w", count );
   strcat(output,buf2);
   page_to_char( output, ch );
    return;
}




 =============================================================================
/   ______ _______ ____   _____   ___ __    _ ______    ____  ____   _____   /
\  |  ____|__   __|  _ \ / ____\ / _ \| \  / |  ____|  / __ \|  _ \ / ____\  \
/  | |__     | |  | |_| | |     | |_| | |\/| | |___   | |  | | |_| | |       /
/  | ___|    | |  | ___/| |   __|  _  | |  | | ____|  | |  | |  __/| |   ___ \
\  | |       | |  | |   | |___| | | | | |  | | |____  | |__| | |\ \| |___| | /
/  |_|       |_|  |_|  o \_____/|_| |_|_|  |_|______|o \____/|_| \_|\_____/  \
\                                                                            /
 ============================================================================

------------------------------------------------------------------------------
ftp://ftp.game.org/pub/mud      FTP.GAME.ORG      http://www.game.org/ftpsite/
------------------------------------------------------------------------------

 This file came from FTP.GAME.ORG, the ultimate source for MUD resources.

------------------------------------------------------------------------------