24 Dec, 2008, Igabod wrote in the 1st comment:
Votes: 0
I'm trying to edit the do_who function that comes with stock low4 so that doesn't show different class names for different generations. I've already made a lot of changes to it but I've run into an interesting problem that I need help with.

I'll start by describing my problem then I'll show you what I've got for a do_who function.

do_who shows every classed avatar and all the mortals and immortals correctly but whenever I log on with an avatar with no class It displays the class incorrectly. My imm char is classed as a werewolf so when my Imm is the only one on, my classless avatar "Nonetest" is displayed as a werewolf. Whenever I log on with my highlander too, Nonetest is displayed as a highlander. The weird thing though, is that if I shut down the mud then restart it and Nonetest is the first to log on, he is displayed semi-correctly, in that it doesn't show any class name at all. But if I log on as any classed char, log off then log on with nonetest as the only active player, he is displayed as whatever class the last person on was. This is a very weird problem to me and I could use some help figuring it out. Here's my do_who function:

void do_newwho(CHAR_DATA *ch,char *argument)
{
char buf[MAX_STRING_LENGTH];
char buf2[MAX_STRING_LENGTH];
char mort[MAX_STRING_LENGTH];
char avat[MAX_STRING_LENGTH];
char god[MAX_STRING_LENGTH];
char a1[MAX_STRING_LENGTH];
char a2[MAX_STRING_LENGTH];
char a3[MAX_STRING_LENGTH];
char a4[MAX_STRING_LENGTH];
char a5[MAX_STRING_LENGTH];
char a6[MAX_STRING_LENGTH];
char a7[MAX_STRING_LENGTH];
char a0[MAX_STRING_LENGTH];
char immo[MAX_STRING_LENGTH];
char kav[MAX_STRING_LENGTH];
char bty[MAX_STRING_LENGTH];
char wizi[MAX_STRING_LENGTH];
char openb[5];
char namething[MAX_STRING_LENGTH];
char closeb[5];
DESCRIPTOR_DATA *d;
int iLevelLower;
int iLevelUpper;
int nNumber;
int immMatch, nMatch;
int mor, ava, imm;
bool fClassRestrict;
bool fImmortalOnly;
if (IS_NPC(ch)) return;

/*
* Set default arguments.
*/
iLevelLower = 0;
iLevelUpper = MAX_LEVEL +1;
fClassRestrict = FALSE;
fImmortalOnly = FALSE;

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

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

if ( is_number( arg ) )
{
stc("Enter 'Avatar' for level 3's, or 'God' for level 4's and 5's.
\r",ch);
return;
}
else
{
/*
* Look for classes to turn on.
*/
arg[3] = '\0';
if (!str_cmp(arg,"imm") || !str_cmp(arg,"immortal")
|| !str_cmp(arg,"ava") || !str_cmp(arg,"avatar"))
{
fClassRestrict = TRUE;
}
else if (!str_cmp(arg,"god") || !str_cmp(arg,"imp"))
{
fImmortalOnly = TRUE;
}
else
{
stc("Enter 'Avatar' for level 3's, or 'God' for level 4's and 5's.
\r",ch);
return;
}
}
}

/*
* Now show matching chars.
*/
immMatch = 0;
nMatch = 0;
buf[0] = '\0';
mort[0] = '\0';
avat[0] = '\0';
immo[0] = '\0';
a1[0] = '\0';
a2[0] = '\0';
a3[0] = '\0';
a4[0] = '\0';
a5[0] = '\0';
a6[0] = '\0';
a7[0] = '\0';
a0[0] = '\0';

mor = ava = imm = 0;
for ( d = descriptor_list; d != NULL; d = d->next )
{
CHAR_DATA *wch;
char const *class;
char const *lstatus;

/*
* Check for match against restrictions.
* Don't use trust as that exposes trusted mortals.
*/
if (d->connected != CON_PLAYING || (!can_see(ch,d->character) && (!IS_SET(ch->act,PLR_WATCHER))))
continue;

wch = (d->original != NULL) ? d->original : d->character;
if (wch->level <iLevelLower>level > iLevelUpper
|| (fImmortalOnly && wch->level <LEVEL_IMMORTAL>level != LEVEL_HERO))
continue;

if IS_IMMORTAL(wch)
immMatch++;
else
nMatch++;
/*
* Figure out what to print for class.
*/
class = " ";
lstatus = " ";



if (IS_SET(wch->extra,EXTRA_AFK)) class = "#r->AFK<-#n ";

switch( wch->lstatus )
{
default: lstatus = "{DUnknown {x"; break;
case L_CIT: lstatus = "{mCitizen {x"; break;
case L_LEG: lstatus = "{bLegend {x"; break;
case L_MYT: lstatus = "{YMyth {x"; break;
case L_TIT: lstatus = "{BTitan {x"; break;
case L_ORA: lstatus = "{COracle {x"; break;
case L_IMM: lstatus = "{rImmortal{x"; break;
case L_DEM: lstatus = "{CDemigod {x"; break;
case L_DEI: lstatus = "{RDeity {x"; break;
case L_ALM: lstatus = "{WAlmighty{x"; break;
}

if ((IS_HEAD(wch,LOST_HEAD) || IS_EXTRA(wch,EXTRA_OSWITCH)) && wch->pcdata->chobj != NULL)
{
if (wch->pcdata->chobj->pIndexData->vnum == 12)
lstatus = " A Head ";
else if (wch->pcdata->chobj->pIndexData->vnum == 30005)
lstatus = "A Brain ";
else
lstatus = "-Object-";
}

switch ( wch->level )
{
default: break;
case MAX_LEVEL - 0:
if (!str_cmp(wch->name,"Igabod"))
class= "#c Owner #n";
else if (!str_cmp(wch->name,"NONAME"))
class= "WHONAMEHERE";
else class = "#rImplementor#n"; break;
case MAX_LEVEL - 1:
class = "#y HighJudge #n"; break;
case MAX_LEVEL - 2:
class = "#g Judge #n"; break;
case MAX_LEVEL - 3:
class = "#c Enforcer #n"; break;
case MAX_LEVEL - 4:
class = "#pQuest Maker#n"; break;
case MAX_LEVEL - 5:
class = "#b Builder #n"; break;
case MAX_LEVEL - 6:
case MAX_LEVEL - 7:
case MAX_LEVEL - 8:
case MAX_LEVEL - 9:

if (wch->race <0>race <10>race <20>race <30>race <40>race <50>race <60>class > 0)
{
if (IS_CLASS(wch,CLASS_VAMPIRE))
sprintf(kav,"%sVampire%s",openb,closeb);
if (IS_CLASS(wch,CLASS_WEREWOLF))
sprintf(kav,"%sWerewolf%s",openb,closeb);
if (IS_CLASS(wch,CLASS_DEMON))
sprintf(kav,"%sDemon%s",openb,closeb);
if (IS_CLASS(wch,CLASS_NINJA))
sprintf(kav,"%sNinja%s",openb,closeb);
if (IS_CLASS(wch,CLASS_DROW))
sprintf(kav,"%sDrow%s",openb,closeb);
if (IS_CLASS(wch,CLASS_MONK))
sprintf(kav,"%sMonk%s",openb,closeb);
if (IS_CLASS(wch,CLASS_HIGHLANDER))
sprintf(kav,"%sHighlander%s",openb,closeb);
if (IS_CLASS(wch,CLASS_MOOGLE))
sprintf(kav,"%sMoogle%s",openb,closeb);
}
else if (IS_CLASS(wch,CLASS_NONE))
sprintf(kav,"%sNone%s",openb,closeb);

if (wch->pcdata->bounty > 0)
sprintf(bty,"%d",wch->pcdata->bounty);
else
strcpy( bty, " ");

if (wch->pcdata->wizinvis> 6)
sprintf(wizi," (%d)",wch->pcdata->wizinvis);
else
strcpy(wizi,"");
sprintf(namething,"#y%s#e%s",wch->name,wch->pcdata->title);

if (wch->level > 6)
{
sprintf(immo + strlen(immo),"{m[{x%s{m]{D%s {m[{x%s{m]{Y %s#e%-21s#n%-20s %s
\r",
class,wizi,lstatus,wch->name,wch->pcdata->title,kav,king_table[wch->pcdata->kingdom].who_name);
imm++;
}
else if (wch->level > 2 && wch->level <7>pcdata->kingdom].who_name);
ava++;
}
else
{
sprintf(mort + strlen(mort),"{m[%s{m]{x %-31s %s
\r",
class,namething,king_table[wch->pcdata->kingdom].who_name);
mor++;
}
}

stc("
\r",ch);
stc("{m+=–=+=–=+=–=+=–=+=–=+=–=+ {CName Pending Mud {m+=–=+=–=+=–=+=–=+=–=+=–=+{x\r",ch);
stc(" #n
\r",ch);
if (ava > 0)
{
if (ava > 1)
sprintf(buf,"{m+=–=+=–=+=–=+=–=+=–=+=–=+ {CAvatars {m+=–=+=–=+=–=+=–=+=–=+=–=+{x\r");
else
sprintf(buf,"{m+=–=+=–=+=–=+=–=+=–=+=–=+ {CAvatars {m+=–=+=–=+=–=+=–=+=–=+=–=+{x\r");
stc(buf,ch);
stc(a0,ch);
}

if (mor > 0)
{
if (mor > 1)
sprintf(buf,"{m+=–=+=–=+=–=+=–=+=–=+=–=+ {GMortals {m+=–=+=–=+=–=+=–=+=–=+=–=+{x\r");
else
sprintf(buf,"{m+=–=+=–=+=–=+=–=+=–=+=–=+ {GMortals {m+=–=+=–=+=–=+=–=+=–=+=–=+{x\r");
stc(buf,ch);
stc(mort,ch);
}

if (imm > 0)
{
if (imm > 1)
sprintf(god,"{m+=–=+=–=+=–=+=–=+=–=+=–=+ {YImmortals {m+=–=+=–=+=–=+=–=+=–=+=–=+{x\r");
else

sprintf(god,"{m+=–=+=–=+=–=+=–=+=–=+=–=+ {YImmortals {m+=–=+=–=+=–=+=–=+=–=+=–=+{x\r");
stc(god,ch);
stc(immo,ch);
}

if (immMatch == 1)
sprintf(god,"#wThere is 1 visible immortal connected.#n");
else if (immMatch > 1)
sprintf(god,"#wThere are a total of %d visible immortals connected.#n",immMatch);

if (nMatch == 1)
sprintf(buf2,"#wThere is 1 visible player connected.#n");
else
sprintf(buf2,"#wThere are a total of %d visible players connected.#n",nMatch);
stc("{m+=–=+=–=+=–=+=–=+=–=+=–=+=–=+=–=+=–=+=–=+=–=+=–=+=–=+=–=+=–=+=–={x
\r",ch);
if (nMatch > 0)
cent_to_char(buf2,ch);
if (imm > 0)
cent_to_char(god,ch);
stc("{m+=–=+=–=+=–=+=–=+=–=+=–=+=–=+=–=+=–=+=–=+=–=+=–=+=–=+=–=+=–=+=–={x
\r",ch);
return;

}


I know, it's kinda long but it's a LOT shorter than the original do_who was. It's pretty sloppy right now but I haven't gotten around to cleaning it up yet, that will have to wait till I get this working correctly.
24 Dec, 2008, Davion wrote in the 2nd comment:
Votes: 0
if (IS_CLASS(wch,CLASS_VAMPIRE))
sprintf(kav,"%sVampire%s",openb,closeb);
if (IS_CLASS(wch,CLASS_WEREWOLF))
sprintf(kav,"%sWerewolf%s",openb,closeb);
if (IS_CLASS(wch,CLASS_DEMON))
sprintf(kav,"%sDemon%s",openb,closeb);
if (IS_CLASS(wch,CLASS_NINJA))
sprintf(kav,"%sNinja%s",openb,closeb);
if (IS_CLASS(wch,CLASS_DROW))
sprintf(kav,"%sDrow%s",openb,closeb);
if (IS_CLASS(wch,CLASS_MONK))
sprintf(kav,"%sMonk%s",openb,closeb);
if (IS_CLASS(wch,CLASS_HIGHLANDER))
sprintf(kav,"%sHighlander%s",openb,closeb);
if (IS_CLASS(wch,CLASS_MOOGLE))
sprintf(kav,"%sMoogle%s",openb,closeb);
}
else if (IS_CLASS(wch,CLASS_NONE))
sprintf(kav,"%sNone%s",openb,closeb);


This seems odd to me. You'll likely want the CLASS_NONE part as part of the elseif statement. So try this
if (IS_CLASS(wch,CLASS_VAMPIRE))
sprintf(kav,"%sVampire%s",openb,closeb);
if (IS_CLASS(wch,CLASS_WEREWOLF))
sprintf(kav,"%sWerewolf%s",openb,closeb);
if (IS_CLASS(wch,CLASS_DEMON))
sprintf(kav,"%sDemon%s",openb,closeb);
if (IS_CLASS(wch,CLASS_NINJA))
sprintf(kav,"%sNinja%s",openb,closeb);
if (IS_CLASS(wch,CLASS_DROW))
sprintf(kav,"%sDrow%s",openb,closeb);
if (IS_CLASS(wch,CLASS_MONK))
sprintf(kav,"%sMonk%s",openb,closeb);
if (IS_CLASS(wch,CLASS_HIGHLANDER))
sprintf(kav,"%sHighlander%s",openb,closeb);
if (IS_CLASS(wch,CLASS_MOOGLE))
sprintf(kav,"%sMoogle%s",openb,closeb);
if (IS_CLASS(wch,CLASS_NONE))
sprintf(kav,"%sNone%s",openb,closeb);
24 Dec, 2008, Lobotomy wrote in the 3rd comment:
Votes: 0
As an aside, with regards to making the code a bit cleaner it helps to use typedefs to cut down on sections like this where you have many things declared in the same way:

I.e, take something like this:
char buf[MAX_STRING_LENGTH];
char buf2[MAX_STRING_LENGTH];
char mort[MAX_STRING_LENGTH];
char avat[MAX_STRING_LENGTH];
char god[MAX_STRING_LENGTH];
char a1[MAX_STRING_LENGTH];
char a2[MAX_STRING_LENGTH];
char a3[MAX_STRING_LENGTH];
char a4[MAX_STRING_LENGTH];
char a5[MAX_STRING_LENGTH];
char a6[MAX_STRING_LENGTH];
char a7[MAX_STRING_LENGTH];
char a0[MAX_STRING_LENGTH];
char immo[MAX_STRING_LENGTH];
char kav[MAX_STRING_LENGTH];
char bty[MAX_STRING_LENGTH];
char wizi[MAX_STRING_LENGTH];

And turn it into something like this:
typedef char charmax[MAX_STRING_LENGTH];

charmax buf, buf2, mort, avat, god, a[8], immo, kav, bty, wizi, (etc ad nauseam);
24 Dec, 2008, Igabod wrote in the 4th comment:
Votes: 0
Davion said:
if (IS_CLASS(wch,CLASS_VAMPIRE))
sprintf(kav,"%sVampire%s",openb,closeb);
if (IS_CLASS(wch,CLASS_WEREWOLF))
sprintf(kav,"%sWerewolf%s",openb,closeb);
if (IS_CLASS(wch,CLASS_DEMON))
sprintf(kav,"%sDemon%s",openb,closeb);
if (IS_CLASS(wch,CLASS_NINJA))
sprintf(kav,"%sNinja%s",openb,closeb);
if (IS_CLASS(wch,CLASS_DROW))
sprintf(kav,"%sDrow%s",openb,closeb);
if (IS_CLASS(wch,CLASS_MONK))
sprintf(kav,"%sMonk%s",openb,closeb);
if (IS_CLASS(wch,CLASS_HIGHLANDER))
sprintf(kav,"%sHighlander%s",openb,closeb);
if (IS_CLASS(wch,CLASS_MOOGLE))
sprintf(kav,"%sMoogle%s",openb,closeb);
}
else if (IS_CLASS(wch,CLASS_NONE))
sprintf(kav,"%sNone%s",openb,closeb);


This seems odd to me. You'll likely want the CLASS_NONE part as part of the elseif statement. So try this
if (IS_CLASS(wch,CLASS_VAMPIRE))
sprintf(kav,"%sVampire%s",openb,closeb);
if (IS_CLASS(wch,CLASS_WEREWOLF))
sprintf(kav,"%sWerewolf%s",openb,closeb);
if (IS_CLASS(wch,CLASS_DEMON))
sprintf(kav,"%sDemon%s",openb,closeb);
if (IS_CLASS(wch,CLASS_NINJA))
sprintf(kav,"%sNinja%s",openb,closeb);
if (IS_CLASS(wch,CLASS_DROW))
sprintf(kav,"%sDrow%s",openb,closeb);
if (IS_CLASS(wch,CLASS_MONK))
sprintf(kav,"%sMonk%s",openb,closeb);
if (IS_CLASS(wch,CLASS_HIGHLANDER))
sprintf(kav,"%sHighlander%s",openb,closeb);
if (IS_CLASS(wch,CLASS_MOOGLE))
sprintf(kav,"%sMoogle%s",openb,closeb);
if (IS_CLASS(wch,CLASS_NONE))
sprintf(kav,"%sNone%s",openb,closeb);

I tried that first and got the exact same results. I've tried just about everything I can think of and nothing changes it at all.

And to lobotomy, thank you I'll certainly do that when I get around to cleaning up the code. That's just how it was done in the stock code.
24 Dec, 2008, Sharmair wrote in the 5th comment:
Votes: 0
The code you posted is too corrupted (probably in the paste as it would not compile as shown) to
tell much of anything for sure. But it does look like you are not covering all the control paths and
leaving something uninitialized (probably the buffer kav or class). The code for printing avatars is
totally corrupted so I can't tell what is used there, but it seems mor does not use kav at all and only
class, but in the code you show, class seems to be only imm rank. It would be helpful to know what
that if is before the block of code with all the kav setting, as if you left it in, it might exclude the case
of CLASS_NONE. You could try replacing:
if (wch->race <0>race <10>race <20>race <30>race <40>race <50>race <60>class > 0)
{
if (IS_CLASS(wch,CLASS_VAMPIRE))
sprintf(kav,"%sVampire%s",openb,closeb);
if (IS_CLASS(wch,CLASS_WEREWOLF))
sprintf(kav,"%sWerewolf%s",openb,closeb);
if (IS_CLASS(wch,CLASS_DEMON))
sprintf(kav,"%sDemon%s",openb,closeb);
if (IS_CLASS(wch,CLASS_NINJA))
sprintf(kav,"%sNinja%s",openb,closeb);
if (IS_CLASS(wch,CLASS_DROW))
sprintf(kav,"%sDrow%s",openb,closeb);
if (IS_CLASS(wch,CLASS_MONK))
sprintf(kav,"%sMonk%s",openb,closeb);
if (IS_CLASS(wch,CLASS_HIGHLANDER))
sprintf(kav,"%sHighlander%s",openb,closeb);
if (IS_CLASS(wch,CLASS_MOOGLE))
sprintf(kav,"%sMoogle%s",openb,closeb);
}
else if (IS_CLASS(wch,CLASS_NONE))
sprintf(kav,"%sNone%s",openb,closeb);

with:
if (IS_CLASS(wch,CLASS_VAMPIRE))
sprintf(kav,"%sVampire%s",openb,closeb);
else if (IS_CLASS(wch,CLASS_WEREWOLF))
sprintf(kav,"%sWerewolf%s",openb,closeb);
else if (IS_CLASS(wch,CLASS_DEMON))
sprintf(kav,"%sDemon%s",openb,closeb);
else if (IS_CLASS(wch,CLASS_NINJA))
sprintf(kav,"%sNinja%s",openb,closeb);
else if (IS_CLASS(wch,CLASS_DROW))
sprintf(kav,"%sDrow%s",openb,closeb);
else if (IS_CLASS(wch,CLASS_MONK))
sprintf(kav,"%sMonk%s",openb,closeb);
else if (IS_CLASS(wch,CLASS_HIGHLANDER))
sprintf(kav,"%sHighlander%s",openb,closeb);
else if (IS_CLASS(wch,CLASS_MOOGLE))
sprintf(kav,"%sMoogle%s",openb,closeb);
else
sprintf(kav,"%sNone%s",openb,closeb);

You might want to try to post the code again, and make sure it shows here right.
24 Dec, 2008, Fizban wrote in the 6th comment:
Votes: 0
Davion said:
if (IS_CLASS(wch,CLASS_VAMPIRE))
sprintf(kav,"%sVampire%s",openb,closeb);
if (IS_CLASS(wch,CLASS_WEREWOLF))
sprintf(kav,"%sWerewolf%s",openb,closeb);
if (IS_CLASS(wch,CLASS_DEMON))
sprintf(kav,"%sDemon%s",openb,closeb);
if (IS_CLASS(wch,CLASS_NINJA))
sprintf(kav,"%sNinja%s",openb,closeb);
if (IS_CLASS(wch,CLASS_DROW))
sprintf(kav,"%sDrow%s",openb,closeb);
if (IS_CLASS(wch,CLASS_MONK))
sprintf(kav,"%sMonk%s",openb,closeb);
if (IS_CLASS(wch,CLASS_HIGHLANDER))
sprintf(kav,"%sHighlander%s",openb,closeb);
if (IS_CLASS(wch,CLASS_MOOGLE))
sprintf(kav,"%sMoogle%s",openb,closeb);
}
else if (IS_CLASS(wch,CLASS_NONE))
sprintf(kav,"%sNone%s",openb,closeb);


This seems odd to me. You'll likely want the CLASS_NONE part as part of the elseif statement. So try this
if (IS_CLASS(wch,CLASS_VAMPIRE))
sprintf(kav,"%sVampire%s",openb,closeb);
if (IS_CLASS(wch,CLASS_WEREWOLF))
sprintf(kav,"%sWerewolf%s",openb,closeb);
if (IS_CLASS(wch,CLASS_DEMON))
sprintf(kav,"%sDemon%s",openb,closeb);
if (IS_CLASS(wch,CLASS_NINJA))
sprintf(kav,"%sNinja%s",openb,closeb);
if (IS_CLASS(wch,CLASS_DROW))
sprintf(kav,"%sDrow%s",openb,closeb);
if (IS_CLASS(wch,CLASS_MONK))
sprintf(kav,"%sMonk%s",openb,closeb);
if (IS_CLASS(wch,CLASS_HIGHLANDER))
sprintf(kav,"%sHighlander%s",openb,closeb);
if (IS_CLASS(wch,CLASS_MOOGLE))
sprintf(kav,"%sMoogle%s",openb,closeb);
if (IS_CLASS(wch,CLASS_NONE))
sprintf(kav,"%sNone%s",openb,closeb);


That'd cause the following check to be ignored.

if (wch->race <0>race <10>race <20>race <30>race <40>race <50>race <60>class > 0)


Whether that would be beneficial or not though I have no clue due to not knowing anything about the codebase in question and as such don't actually know exactly what that if check is checking.
24 Dec, 2008, Fizban wrote in the 7th comment:
Votes: 0
Whoops, posted at the same time as Sharmair.
24 Dec, 2008, Sharmair wrote in the 8th comment:
Votes: 0
Fizban said:
if (wch->race <0>race <10>race <20>race <30>race <40>race <50>race <60>class > 0)


Whether that would be beneficial or not though I have no clue due to not knowing anything about the codebase in question and as such don't actually know exactly what that if check is checking.

Yea, that is one of the lines I am pretty sure is corrupted. Though as a side note, if race was defined
it would actually be valid C. It would be chaining a bunch on compares (in most cases using TRUE or
FALSE as arguments). Though valid, probably not too useful.
25 Dec, 2008, Igabod wrote in the 9th comment:
Votes: 0
yeah maybe I should check everything i paste in before I submit it. sorry, here's the (hopefully) correct function.

void do_newwho(CHAR_DATA *ch,char *argument)
{
char buf[MAX_STRING_LENGTH];
char buf2[MAX_STRING_LENGTH];
char mort[MAX_STRING_LENGTH];
char avat[MAX_STRING_LENGTH];
char god[MAX_STRING_LENGTH];
char a1[MAX_STRING_LENGTH];
char a2[MAX_STRING_LENGTH];
char a3[MAX_STRING_LENGTH];
char a4[MAX_STRING_LENGTH];
char a5[MAX_STRING_LENGTH];
char a6[MAX_STRING_LENGTH];
char a7[MAX_STRING_LENGTH];
char a0[MAX_STRING_LENGTH];
char immo[MAX_STRING_LENGTH];
char kav[MAX_STRING_LENGTH];
char bty[MAX_STRING_LENGTH];
char wizi[MAX_STRING_LENGTH];
char openb[5];
char namething[MAX_STRING_LENGTH];
char closeb[5];
DESCRIPTOR_DATA *d;
int iLevelLower;
int iLevelUpper;
int nNumber;
int immMatch, nMatch;
int mor, ava, imm;
bool fClassRestrict;
bool fImmortalOnly;
if (IS_NPC(ch)) return;

/*
* Set default arguments.
*/
iLevelLower = 0;
iLevelUpper = MAX_LEVEL +1;
fClassRestrict = FALSE;
fImmortalOnly = FALSE;

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

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

if ( is_number( arg ) )
{
stc("Enter 'Avatar' for level 3's, or 'God' for level 4's and 5's.\n\r",ch);
return;
}
else
{
/*
* Look for classes to turn on.
*/
arg[3] = '\0';
if (!str_cmp(arg,"imm") || !str_cmp(arg,"immortal")
|| !str_cmp(arg,"ava") || !str_cmp(arg,"avatar"))
{
fClassRestrict = TRUE;
}
else if (!str_cmp(arg,"god") || !str_cmp(arg,"imp"))
{
fImmortalOnly = TRUE;
}
else
{
stc("Enter 'Avatar' for level 3's, or 'God' for level 4's and 5's.\n\r",ch);
return;
}
}
}

/*
* Now show matching chars.
*/
immMatch = 0;
nMatch = 0;
buf[0] = '\0';
mort[0] = '\0';
avat[0] = '\0';
immo[0] = '\0';
a1[0] = '\0';
a2[0] = '\0';
a3[0] = '\0';
a4[0] = '\0';
a5[0] = '\0';
a6[0] = '\0';
a7[0] = '\0';
a0[0] = '\0';

mor = ava = imm = 0;
for ( d = descriptor_list; d != NULL; d = d->next )
{
CHAR_DATA *wch;
char const *class;
char const *lstatus;

/*
* Check for match against restrictions.
* Don't use trust as that exposes trusted mortals.
*/
if (d->connected != CON_PLAYING || (!can_see(ch,d->character) && (!IS_SET(ch->act,PLR_WATCHER))))
continue;

wch = (d->original != NULL) ? d->original : d->character;
if (wch->level < iLevelLower || wch->level > iLevelUpper
|| (fImmortalOnly && wch->level < LEVEL_IMMORTAL)
|| (fClassRestrict && wch->level != LEVEL_HERO))
continue;

if IS_IMMORTAL(wch)
immMatch++;
else
nMatch++;
/*
* Figure out what to print for class.
*/
class = " ";
lstatus = " ";



if (IS_SET(wch->extra,EXTRA_AFK)) class = "#r->AFK<-#n ";

switch( wch->lstatus )
{
default: lstatus = "{DUnknown {x"; break;
case L_CIT: lstatus = "{mCitizen {x"; break;
case L_LEG: lstatus = "{bLegend {x"; break;
case L_MYT: lstatus = "{YMyth {x"; break;
case L_TIT: lstatus = "{BTitan {x"; break;
case L_ORA: lstatus = "{COracle {x"; break;
case L_IMM: lstatus = "{rImmortal{x"; break;
case L_DEM: lstatus = "{CDemigod {x"; break;
case L_DEI: lstatus = "{RDeity {x"; break;
case L_ALM: lstatus = "{WAlmighty{x"; break;
}

if ((IS_HEAD(wch,LOST_HEAD) || IS_EXTRA(wch,EXTRA_OSWITCH)) && wch->pcdata->chobj != NULL)
{
if (wch->pcdata->chobj->pIndexData->vnum == 12)
lstatus = " A Head ";
else if (wch->pcdata->chobj->pIndexData->vnum == 30005)
lstatus = "A Brain ";
else
lstatus = "-Object-";
}

switch ( wch->level )
{
default: break;
case MAX_LEVEL - 0:
if (!str_cmp(wch->name,"Igabod"))
class= "#c Owner #n";
else if (!str_cmp(wch->name,"NONAME"))
class= "WHONAMEHERE";
else class = "#rImplementor#n"; break;
case MAX_LEVEL - 1:
class = "#y HighJudge #n"; break;
case MAX_LEVEL - 2:
class = "#g Judge #n"; break;
case MAX_LEVEL - 3:
class = "#c Enforcer #n"; break;
case MAX_LEVEL - 4:
class = "#pQuest Maker#n"; break;
case MAX_LEVEL - 5:
class = "#b Builder #n"; break;
case MAX_LEVEL - 6:
case MAX_LEVEL - 7:
case MAX_LEVEL - 8:
case MAX_LEVEL - 9:

if (wch->race <= 0 )
class = "#r Avatar #n";
else if (wch->race <= 10)
class = "#b Immortal #n";
else if (wch->race <= 20)
class = "#g Godling #n";
else if (wch->race <= 30)
class = "#y Demigod #n";
else if (wch->race <= 40)
class = "#cLesser God #n";
else if (wch->race <= 50)
class = "#pGreater God#n";
else if (wch->race <= 60)
class = "#wSupreme God#n";
else
class = "#wSupreme God#n"; break;
case MAX_LEVEL - 10:
class = "#y Mortal #n"; break;
case MAX_LEVEL - 11:
class = "#y Mortal #n"; break;
case MAX_LEVEL - 12:
class = "#y Newbie #n"; break;
}

/*
* Format it up.
*/
if (IS_CLASS(wch,CLASS_VAMPIRE))
{
strcpy(openb,"{r<<-");
strcpy(closeb,"->>{x");
}
else if (IS_CLASS(wch,CLASS_WEREWOLF))
{
strcpy(openb,"{y-+(");
strcpy(closeb,")+-{x");
}
else if (IS_CLASS(wch,CLASS_HIGHLANDER))
{
strcpy(openb,"{C-=");
strcpy(closeb,"=-{x");
}
else if (IS_CLASS(wch,CLASS_NINJA))
{
strcpy(openb," {m*+*");
strcpy(closeb, "*+*{x");
}
else if (IS_CLASS(wch,CLASS_MOOGLE))
{
strcpy(openb," {Y-=+{W");
strcpy(closeb,"{Y+=-{x ");
}
else if (IS_CLASS(wch,CLASS_MONK))
{
strcpy(openb,"{c(O0o.{C");
strcpy(closeb,"{c.o0O){x ");
}
else if (IS_CLASS(wch,CLASS_DROW))
{
strcpy(openb,"{b.o0 ");
strcpy(closeb," 0o.{x" );
}
else if (IS_CLASS(wch,CLASS_NONE))
{
strcpy(openb,"{D….");
strcpy(closeb,"….{x");}
else if (IS_CLASS(wch,CLASS_DEMON))
{
strcpy(openb," {R[-]");
strcpy(closeb,"[-]{x");
}
if (ch->class > 0)
{
if (IS_CLASS(wch,CLASS_VAMPIRE))
sprintf(kav,"%sVampire%s",openb,closeb);
if (IS_CLASS(wch,CLASS_WEREWOLF))
sprintf(kav,"%sWerewolf%s",openb,closeb);
if (IS_CLASS(wch,CLASS_DEMON))
sprintf(kav,"%sDemon%s",openb,closeb);
if (IS_CLASS(wch,CLASS_NINJA))
sprintf(kav,"%sNinja%s",openb,closeb);
if (IS_CLASS(wch,CLASS_DROW))
sprintf(kav,"%sDrow%s",openb,closeb);
if (IS_CLASS(wch,CLASS_MONK))
sprintf(kav,"%sMonk%s",openb,closeb);
if (IS_CLASS(wch,CLASS_HIGHLANDER))
sprintf(kav,"%sHighlander%s",openb,closeb);
if (IS_CLASS(wch,CLASS_MOOGLE))
sprintf(kav,"%sMoogle%s",openb,closeb);
}
else if (IS_CLASS(wch,CLASS_NONE))
sprintf(kav,"%sNone%s",openb,closeb);

if (wch->pcdata->bounty > 0)
sprintf(bty,"%d",wch->pcdata->bounty);
else
strcpy( bty, " ");

if (wch->pcdata->wizinvis> 6)
sprintf(wizi," (%d)",wch->pcdata->wizinvis);
else
strcpy(wizi,"");
sprintf(namething,"#y%s#e%s",wch->name,wch->pcdata->title);

if (wch->level > 6)
{
sprintf(immo + strlen(immo),"{m[{x%s{m]{D%s {m[{x%s{m]{Y %s#e%-21s#n%-20s %s\n\r",
class,wizi,lstatus,wch->name,wch->pcdata->title,kav,king_table[wch->pcdata->kingdom].who_name);
imm++;
}
else if (wch->level > 2 && wch->level < 7)
{
sprintf(a0 + strlen(a0),"{m[{x%s{m]{x {m[{x%s{m]{x %-31s%-20s %s\n\r",
class,lstatus,namething,kav,king_table[wch->pcdata->kingdom].who_name);
ava++;
}
else
{
sprintf(mort + strlen(mort),"{m[%s{m]{x %-31s %s\n\r",
class,namething,king_table[wch->pcdata->kingdom].who_name);
mor++;
}
}

stc("\n\r",ch);
stc("{m+=–=+=–=+=–=+=–=+=–=+=–=+ {CName Pending Mud {m+=–=+=–=+=–=+=–=+=–=+=–=+{x\n\r",ch);
stc(" #n\n\r",ch);
if (ava > 0)
{
if (ava > 1)
sprintf(buf,"{m+=–=+=–=+=–=+=–=+=–=+=–=+ {CAvatars {m+=–=+=–=+=–=+=–=+=–=+=–=+{x\n\r");
else
sprintf(buf,"{m+=–=+=–=+=–=+=–=+=–=+=–=+ {CAvatars {m+=–=+=–=+=–=+=–=+=–=+=–=+{x\n\r");
stc(buf,ch);
stc(a0,ch);
}

if (mor > 0)
{
if (mor > 1)
sprintf(buf,"{m+=–=+=–=+=–=+=–=+=–=+=–=+ {GMortals {m+=–=+=–=+=–=+=–=+=–=+=–=+{x\n\r");
else
sprintf(buf,"{m+=–=+=–=+=–=+=–=+=–=+=–=+ {GMortals {m+=–=+=–=+=–=+=–=+=–=+=–=+{x\n\r");
stc(buf,ch);
stc(mort,ch);
}

if (imm > 0)
{
if (imm > 1)
sprintf(god,"{m+=–=+=–=+=–=+=–=+=–=+=–=+ {YImmortals {m+=–=+=–=+=–=+=–=+=–=+=–=+{x\n\r");
else

sprintf(god,"{m+=–=+=–=+=–=+=–=+=–=+=–=+ {YImmortals {m+=–=+=–=+=–=+=–=+=–=+=–=+{x\n\r");
stc(god,ch);
stc(immo,ch);
}

if (immMatch == 1)
sprintf(god,"#wThere is 1 visible immortal connected.#n");
else if (immMatch > 1)
sprintf(god,"#wThere are a total of %d visible immortals connected.#n",immMatch);

if (nMatch == 1)
sprintf(buf2,"#wThere is 1 visible player connected.#n");
else
sprintf(buf2,"#wThere are a total of %d visible players connected.#n",nMatch);
stc("{m+=–=+=–=+=–=+=–=+=–=+=–=+=–=+=–=+=–=+=–=+=–=+=–=+=–=+=–=+=–=+=–={x\n\r",ch);
if (nMatch > 0)
cent_to_char(buf2,ch);
if (imm > 0)
cent_to_char(god,ch);
stc("{m+=–=+=–=+=–=+=–=+=–=+=–=+=–=+=–=+=–=+=–=+=–=+=–=+=–=+=–=+=–=+=–={x\n\r",ch);
return;

}


ok, that looks right after doing a preview, sorry bout the screwy one, don't know how that happened.
25 Dec, 2008, Igabod wrote in the 10th comment:
Votes: 0
Well, it was something SUPER simple… Tijer pointed it out for me on Godwars.net. The problem is that ch->class > 0 should be wch->class. I feel like a complete retard now.
26 Dec, 2008, Igabod wrote in the 11th comment:
Votes: 0
ok I went home after posting that last post and found out that it wasn't really quite that simple. The references to CLASS_NONE had to be changed to wch->class == 0 as well but now it's really working correctly now, I've fully tested it out.
26 Dec, 2008, Sharmair wrote in the 12th comment:
Votes: 0
Looking over this new code I see you are overrunning a couple buffers. Your openb[] and closeb[]
buffers are defined as 5 char long, but it looks like only HIGHLANDER will fit in (4 char + NUL) without
overrunning. I count some as needing 12 or so chars in the buffer. You might want to change the
5 to something like 16 to make sure you have enough room:
char openb[16];
char closeb[16];

at lines 20 and 22 in your code as shown.

As it looks like these are set by class and are only used in the setting of kav (also by class), you could
combine the steps and just set kav by replacing:
if (IS_CLASS(wch,CLASS_VAMPIRE))
{
strcpy(openb,"{r<<-");
strcpy(closeb,"->>{x");
}
else if (IS_CLASS(wch,CLASS_WEREWOLF))
{
strcpy(openb,"{y-+(");
strcpy(closeb,")+-{x");
}
else if (IS_CLASS(wch,CLASS_HIGHLANDER))
{
strcpy(openb,"{C-=");
strcpy(closeb,"=-{x");
}
else if (IS_CLASS(wch,CLASS_NINJA))
{
strcpy(openb," {m*+*");
strcpy(closeb, "*+*{x");
}
else if (IS_CLASS(wch,CLASS_MOOGLE))
{
strcpy(openb," {Y-=+{W");
strcpy(closeb,"{Y+=-{x ");
}
else if (IS_CLASS(wch,CLASS_MONK))
{
strcpy(openb,"{c(O0o.{C");
strcpy(closeb,"{c.o0O){x ");
}
else if (IS_CLASS(wch,CLASS_DROW))
{
strcpy(openb,"{b.o0 ");
strcpy(closeb," 0o.{x" );
}
else if (IS_CLASS(wch,CLASS_NONE))
{
strcpy(openb,"{D….");
strcpy(closeb,"….{x");}
else if (IS_CLASS(wch,CLASS_DEMON))
{
strcpy(openb," {R[-]");
strcpy(closeb,"[-]{x");
}
if (wch->class > 0)
{
if (IS_CLASS(wch,CLASS_VAMPIRE))
sprintf(kav,"%sVampire%s",openb,closeb);
if (IS_CLASS(wch,CLASS_WEREWOLF))
sprintf(kav,"%sWerewolf%s",openb,closeb);
if (IS_CLASS(wch,CLASS_DEMON))
sprintf(kav,"%sDemon%s",openb,closeb);
if (IS_CLASS(wch,CLASS_NINJA))
sprintf(kav,"%sNinja%s",openb,closeb);
if (IS_CLASS(wch,CLASS_DROW))
sprintf(kav,"%sDrow%s",openb,closeb);
if (IS_CLASS(wch,CLASS_MONK))
sprintf(kav,"%sMonk%s",openb,closeb);
if (IS_CLASS(wch,CLASS_HIGHLANDER))
sprintf(kav,"%sHighlander%s",openb,closeb);
if (IS_CLASS(wch,CLASS_MOOGLE))
sprintf(kav,"%sMoogle%s",openb,closeb);
}
else if (IS_CLASS(wch,CLASS_NONE))
sprintf(kav,"%sNone%s",openb,closeb);

with:
if(IS_CLASS(wch, CLASS_VAMPIRE))
strcpy(kav, "{r<<-Vampire->>{x");
else if(IS_CLASS(wch, CLASS_WEREWOLF))
strcpy(kav, "{y-+(Werewolf)+-{x");
else if(IS_CLASS(wch, CLASS_DEMON))
strcpy(kav, " {R[-]Demon[-]{x");
else if(IS_CLASS(wch, CLASS_NINJA))
strcpy(kav, " {m*+*Ninja*+*{x");
else if(IS_CLASS(wch, CLASS_DROW))
strcpy(kav, "{b.o0 Drow 0o.{x");
else if(IS_CLASS(wch, CLASS_MONK))
strcpy(kav, "{c(O0o.{CMonk{c.o0O){x ");
else if(IS_CLASS(wch, CLASS_HIGHLANDER))
strcpy(kav, "{C-=Highlander=-{x");
else if(IS_CLASS(wch, CLASS_MOOGLE))
strcpy(kav, " {Y-=+{WMoogle{Y+=-{x ");
else
strcpy(kav, "{D….None….{x");

And get rid of openb and closeb entirely. This would be shorter, more efficient and always set
kav (in your case, if class is some odd value it might not fit any of the ifs and not be set - here the
else case at the end will cover CLASS_NONE and any other unhandled value too).
27 Dec, 2008, Igabod wrote in the 13th comment:
Votes: 0
Yeah some of those things are remnants of the original do_who. I'm still not quite done updating it yet. The original do_who gave a different who_name to classes based on their generation and clan. I took out clans however and am using kingdoms.

As to the remark about the buffers being set to 5, you are mistaken. All of them fit, the number is stating that the openb should be 4 characters long, then you've got the class name, then you've got a 4 char closeb.

I've fully tested the alignment under all circumstances, including really long char names and really short char names. Those numbers are exactly what were needed to get it all to line up right.

I appreciate your advice though and will probably do it like that when I get to that step in the progress of cleaning up this do_who function. My main priority was just to get it working right to display everything the way it should be.

Now that I've got that done I get to actually tear it apart and move the pieces around to form a (hopefully) cleaner and more linear function.
27 Dec, 2008, David Haley wrote in the 14th comment:
Votes: 0
Sharmair's right about the size of the buffers… as he said, there is a null character to be counted alongside the four actual characters.
27 Dec, 2008, Igabod wrote in the 15th comment:
Votes: 0
If he was right wouldn't I notice some sort of alignment malfunctions? I've had 8 completely different test characters on at one time to make sure I didn't screw this up. Every single line was perfectly lined up.
27 Dec, 2008, David Haley wrote in the 16th comment:
Votes: 0
I don't know what to tell you, making them size 5 means that exactly 4 non-zero characters will fit followed by one null character. Writing more than 5 bytes means that you're overflowing into whatever buffer comes next – probably one of the other variables. It's possible that by chance the alignment works, but I would be pretty surprised if everything were exactly as it should be.

Sharmair is absolutely correct, though. It is quite simply wrong to write more than 5 bytes into a buffer of size 5. Remember that strings are always terminated by a null character.
27 Dec, 2008, Igabod wrote in the 17th comment:
Votes: 0
I still don't see what you're talking about, I'm not writing more than 5 bytes into those buffers. openb for moogle is -=+ or something like that which is 3 characters, it's got a space in front of it which is 4 and then it's got the other blank space to line it up correctly with the longest class who_name which is highlander. Can you show me what you're talking about here cause I may be misinterpreting what is being said here.
27 Dec, 2008, David Haley wrote in the 18th comment:
Votes: 0
OK, for starters, when programming and especially when looking at things like buffer sizes, "something like that" doesn't really cut it. It is critically important to be completely precise. Let's look at exactly what you're doing…

else if (IS_CLASS(wch,CLASS_MOOGLE))
{
strcpy(openb," {Y-=+{W");
strcpy(closeb,"{Y+=-{x ");
}

You are writing:
1: (space)
2: {
3: Y
4: -
5: =
6: +
7: {
8: W

That's 8 characters. Plus the null character that all strings have, you are writing 9 characters into a buffer that is declared to be of size 5.
27 Dec, 2008, Igabod wrote in the 19th comment:
Votes: 0
there is something in my code somewhere that strips color code from the char count. I'm not sure what it's called but I've come across it in the past and know it's there and that it does that, gotta love comments.

[p.s] and my "something like that" was cause I couldn't remember if it was -=+ or -+= or +=- the order doesn't matter at all, just the number of characters.
27 Dec, 2008, Kayle wrote in the 20th comment:
Votes: 0
Quote
there is something in my code somewhere that strips color code from the char count. I'm not sure what it's called but I've come across it in the past and know it's there and that it does that, gotta love comments.


Color codes, spaces, and the actual stuff going to be displayed are all counted as a character in a string. Every string is NULL-terminated. The function you're referring to is one that skips color codes when counting the length of a string. It does NOT prevent the system from counting a valid member of a string. Everything you put between those quotation marks counts. EVERYTHING.

If you want the help to continue, you need to listen to those trying to help you, and not tell those among us with degrees in the field that they're wrong. You talk big, but so far I haven't seen much to back that up.

[Edit:] strrep( "their", "they\'re" );
0.0/35