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. ------------------------------------------------------------------------------