NEW FEAT: /who [nopet] [sort [...]]

A forum for feature requests/discussions and user submitted patches that improve MQ2

Moderator: MacroQuest Developers

MacroFiend
a grimling bloodguard
a grimling bloodguard
Posts: 662
Joined: Mon Jul 28, 2003 2:47 am

NEW FEAT: /who [nopet] [sort [...]]

Post by MacroFiend » Fri Oct 10, 2003 7:21 pm

This is going to be long and probably messy ... hopefully it'll make enough sense. This will add two new switches to /who. /who sort [name|level|distance|race|class|guild|id] will sort based on the modifier given. If left out, /who will sort by name and then by level as a default.

MQ.h

Code: Select all

[color=red]
	BOOL bKnownLocation;[/color]
	BOOL bNoPet;
	DWORD SortBy;[color=red]
} SEARCHSPAWN, *PSEARCHSPAWN;

typedef struct _SWHOSORT {
	CHAR szName[MAX_STRING];
	CHAR szLine[MAX_STRING];
	BYTE Level;
	DWORD SpawnID;
	FLOAT Distance;[/color]
	DWORD Class;
	DWORD Race;
	DWORD GuildID;[color=red]
} SWHOSORT, *PSWHOSORT;[/color]
Further down in MQ.h

Code: Select all

[color=red]
VOID		SwapSWho				(PSWHOSORT pSWho1, PSWHOSORT pSWho2);[/color]
VOID		SortSWho				(PSWHOSORT pSWhoSort, DWORD SpawnCount, DWORD SortBy = 0);[color=red]
VOID		SuperWhoFindPets		(PSPAWNINFO pChar, WORD SpawnID);[/color]
EQLib_Commands.cpp (There are some big ones)

Code: Select all

// ***************************************************************************
// Function:    SortSWho
// Description: Sorts an array of PSWHOSORT
// ***************************************************************************
VOID SortSWho(PSWHOSORT pSWhoSort, DWORD SpawnCount, DWORD SortBy)
{
	DWORD Index1, Index2;
/*	-- For reference purposes only
	PCHAR szSortBy[] = {
		"level",	// Default sort by
		"name",
		"race",
		"class",
		"distance",
		"guild",
		"id",
		NULL 
	}; 
*/

	// Pre-sort the entire list by name
	for (Index1=0;Index1<SpawnCount;Index1++) {
		for (Index2=SpawnCount-1;Index2>Index1;Index2--) {
			if (stricmp(pSWhoSort[Index2].szName, pSWhoSort[Index2-1].szName)<0) {
				SwapSWho(&pSWhoSort[Index2], &pSWhoSort[Index2-1]);
			}
		}
	}

	switch (SortBy) {
		case 0:
			//Sort by Level
			for (Index1=0;Index1<SpawnCount;Index1++) {
				for (Index2=SpawnCount-1;Index2>Index1;Index2--) {
					if (pSWhoSort[Index2].Level < pSWhoSort[Index2-1].Level) {
						SwapSWho(&pSWhoSort[Index2], &pSWhoSort[Index2-1]);
					}
				}
			}
			break;

		case 1:
			//Sort by Name
			for (Index1=0;Index1<SpawnCount;Index1++) {
				for (Index2=SpawnCount-1;Index2>Index1;Index2--) {
					if (stricmp(pSWhoSort[Index2].szName, pSWhoSort[Index2-1].szName)<0) {
						SwapSWho(&pSWhoSort[Index2], &pSWhoSort[Index2-1]);
					}
				}
			}
			break;

		case 2:
			//Sort by Race
			for (Index1=0;Index1<SpawnCount;Index1++) {
				for (Index2=SpawnCount-1;Index2>Index1;Index2--) {
					if (stricmp(GetRaceByID(pSWhoSort[Index2].Race), GetRaceByID(pSWhoSort[Index2-1].Race))<0) {
						SwapSWho(&pSWhoSort[Index2], &pSWhoSort[Index2-1]);
					}
				}
			}
			break;

		case 3:
			//Sort by Class
			for (Index1=0;Index1<SpawnCount;Index1++) {
				for (Index2=SpawnCount-1;Index2>Index1;Index2--) {
					if (stricmp(GetClassByID(pSWhoSort[Index2].Class), GetClassByID(pSWhoSort[Index2-1].Class))<0) {
						SwapSWho(&pSWhoSort[Index2], &pSWhoSort[Index2-1]);
					}
				}
			}
			break;

		case 4:
			//Sort by Distance
			for (Index1=0;Index1<SpawnCount;Index1++) {
				for (Index2=SpawnCount-1;Index2>Index1;Index2--) {
					if (pSWhoSort[Index2].Distance < pSWhoSort[Index2-1].Distance) {
						SwapSWho(&pSWhoSort[Index2], &pSWhoSort[Index2-1]);
					}
				}
			}
			break;

		case 5:
			//Sort by Guild
			for (Index1=0;Index1<SpawnCount;Index1++) {
				for (Index2=SpawnCount-1;Index2>Index1;Index2--) {
					if (pSWhoSort[Index2].GuildID < pSWhoSort[Index2-1].GuildID) {
						SwapSWho(&pSWhoSort[Index2], &pSWhoSort[Index2-1]);
					}
				}
			}
			break;

		case 6:
			//Sort by Level
			for (Index1=0;Index1<SpawnCount;Index1++) {
				for (Index2=SpawnCount-1;Index2>Index1;Index2--) {
					if (pSWhoSort[Index2].SpawnID < pSWhoSort[Index2-1].SpawnID) {
						SwapSWho(&pSWhoSort[Index2], &pSWhoSort[Index2-1]);
					}
				}
			}
			break;
	}
}
EQLib_Commands.cpp -- Inside SuperWhoDisplay

Code: Select all

[color=red]
		pSWhoSort[SpawnCount].SpawnID = pSpawn->SpawnID;[/color]
		pSWhoSort[SpawnCount].Class = pSpawn->Class;
		pSWhoSort[SpawnCount].Race = pSpawn->Race;
		pSWhoSort[SpawnCount].GuildID = pSpawn->GuildID;[color=red]
		SpawnCount++;
    }
    if (pFilter) {[/color]
		SortSWho(pSWhoSort,SpawnCount,pFilter->SortBy);[color=red]
	} else {[/color]
		SortSWho(pSWhoSort,SpawnCount,0);[color=red]
	}[/color]

Code: Select all

[color=red]
		strcat(szOutput,pSWhoSort[Index].szLine);
		WriteChatColor(szOutput,Color);[/color]
		if ((!pFilter) || (!pFilter->bNoPet)) [color=red]SuperWhoFindPets(pChar, pSWhoSort[Index].SpawnID,(Color!=USERCOLOR_WHO));
	}
	if (pFilter) {
		if (SpawnCount==0) {
[/color]
EQLib_Commands.cpp -- Inside ClearSearchSpawn

Code: Select all

[color=red]
	pSearchSpawn->FromSpawnID = 0;[/color]
	pSearchSpawn->bNoPet = FALSE;
	pSearchSpawn->SortBy = 0;[color=red]
}[/color]
EQLib_Commands.cpp -- Inside ParseSearchSpawnArgs

Code: Select all

[color=red]
        } else if (!strcmp(szArg,"nopcnear")) {
            GetArg(szArg,szRest,1);

            if ((szArg[0]==0) || (0.0f == (pSearchSpawn->Radius = (FLOAT)atof(szArg)))) {
                pSearchSpawn->Radius = 200.0f;
            } else {
                szRest = GetNextArg(szRest,1);
            }[/color]
        } else if (!strcmp(szArg,"nopet")) {
            pSearchSpawn->bNoPet = TRUE;
[color=red]
		} else {
            strcpy(pSearchSpawn->szName,szArg);
            szRest = GetNextArg(szRest,1);
        }
    }
    return szRest;
[/color]
EQCommands.cpp -- Inside FormatSearchSpawn

Code: Select all

[color=red]
    if (pSearchSpawn->bNotNearAlert) {
        sprintf(szTemp," NotNearAlert:%d",pSearchSpawn->NotNearAlertList);
        strcat(Buffer,szTemp);
    }[/color]
    if (pSearchSpawn->bNoPet) {
        sprintf(szTemp," NoPet:%d",pSearchSpawn->bNoPet);
        strcat(Buffer,szTemp);
    }[color=red]
    if (pSearchSpawn->bTrader) strcat(Buffer," Trader");[/color]

EQLib_Commands.cpp -- SuperWho

Code: Select all

// ***************************************************************************
// Function:    SuperWho
// Description: Our '/who' command
//              Displays a list of spawns in the zone
// Usage:       /who <search string>
// ***************************************************************************
VOID SuperWho(PSPAWNINFO pChar, PCHAR szLine)
{
	bRunNextCommand = TRUE;
	DWORD Command=0;
	CHAR szLLine[MAX_STRING] = {0};
	CHAR szArg[MAX_STRING] = {0};
	PCHAR szRest = szLLine;
	BOOL Parsing = TRUE;
	SEARCHSPAWN SearchSpawn;

	PCHAR szSortBy[] = {
		"level",	// Default sort by
		"name",
		"race",
		"class",
		"distance",
		"guild",
		"id",
		NULL 
	};

	_strlwr(strcpy(szLLine,szLine));
	ClearSearchSpawn(&SearchSpawn);
	SearchSpawn.SpawnType = SPAWN_PLAYER;

	if ((!stricmp(szLine,"all")) ||
		(!strnicmp(szLine,"all ",4)) ||
		(!strnicmp(szLine+strlen(szLine)-4," all",4)) ||
		(strstr(szLine," all ")))
	{
		cmdWho(pChar, szLine);
		return;
	}
	if (gFilterMacro == FILTERMACRO_NONE) cmdWho(pChar, szLine);

	while (Parsing) {
		GetArg(szArg,szRest,1);
		szRest = GetNextArg(szRest,1);
		if (szArg[0]==0) {
			Parsing=FALSE;
		} else if (!strcmp(szArg,"sort")) {
			GetArg(szArg,szRest,1);
			Command=0;
			for (Command;szSortBy[Command];Command++) {
				if (!strcmp(szArg,szSortBy[Command])) {
					SearchSpawn.SortBy = Command;
					szRest = GetNextArg(szRest,1);
				}
			}
		} else {
			szRest = ParseSearchSpawnArgs(szArg,szRest,&SearchSpawn);
		}
	}

	DebugSpew("SuperWho - filtering %s",SearchSpawn.szName);
	SuperWhoDisplay(pChar, &SearchSpawn,NULL);

}

*Edited to remove the potential bug Plazmic saw and fixed [nopet] option
*Re-edited to move the sort parser out of ParseSearchSpawnArgs
*Edited to add FormatSearchSpawn so if no entries are found w/ the nopet option enabled, it will include that in the return string.
Last edited by MacroFiend on Sat Oct 11, 2003 1:54 pm, edited 5 times in total.

Plazmic
The One
The One
Posts: 800
Joined: Fri Jun 14, 2002 12:31 am
Contact:

Post by Plazmic » Fri Oct 10, 2003 7:38 pm

I think this will break somethings...

If i read the code right "/who sort level class enchanter" will be interpreted as sort by class, look for spawns named enchanter...
- Plazmic

MacroFiend
a grimling bloodguard
a grimling bloodguard
Posts: 662
Joined: Mon Jul 28, 2003 2:47 am

Post by MacroFiend » Fri Oct 10, 2003 8:13 pm

It should only accept 1 parameter after the sort. I might have misunderstood part of the code though when I added it to ParseSearchSpawnArgs though.

Your example worked as designed though. /who of only enchanters sorted by level

To be safe, I have it breaking out of the for loop when it makes a match.

Plazmic
The One
The One
Posts: 800
Joined: Fri Jun 14, 2002 12:31 am
Contact:

Post by Plazmic » Fri Oct 10, 2003 9:40 pm

Can we move parsing "sort" to SuperWho(), since where it currently lives, it will get parsed during /who, /target, /face, and /where...
- Plazmic

MacroFiend
a grimling bloodguard
a grimling bloodguard
Posts: 662
Joined: Mon Jul 28, 2003 2:47 am

Post by MacroFiend » Fri Oct 10, 2003 9:57 pm

Moved the Arg search for sort out of ParseSearchSpawnArgs and moved it in to SuperWho.

MacroFiend
a grimling bloodguard
a grimling bloodguard
Posts: 662
Joined: Mon Jul 28, 2003 2:47 am

Post by MacroFiend » Sat Oct 11, 2003 1:55 pm

Added a return message to FormatSearchSpawn to add the nopet feature to its return if it is called.

Jaerin
Developer
Developer
Posts: 133
Joined: Mon Mar 10, 2003 7:37 pm
Contact:

Post by Jaerin » Mon Oct 13, 2003 11:13 am

How about adding a parameter to only return a certain number of results. Mainly because sorting by distance, the closest mobs are probably going to scroll off the chat window.

Not enterly useful in macros, but as a playing command it would be nice

Jaerin

MacroFiend
a grimling bloodguard
a grimling bloodguard
Posts: 662
Joined: Mon Jul 28, 2003 2:47 am

Post by MacroFiend » Mon Oct 13, 2003 1:02 pm

Give me a parameter list that wouldn't get easily confused and I'll add it :)

/who max 500 seems a little vague but that's the only thing I can think of at the moment.

MacroFiend
a grimling bloodguard
a grimling bloodguard
Posts: 662
Joined: Mon Jul 28, 2003 2:47 am

Post by MacroFiend » Thu Oct 16, 2003 7:12 pm

Can this get tested/CVS'd? It has been working well for me personally but hasn't made it in the CVS yet.

Mckorr
Developer
Developer
Posts: 2326
Joined: Fri Oct 18, 2002 1:16 pm
Location: Texas

Post by Mckorr » Thu Oct 16, 2003 7:32 pm

We're waiting for you and Plaz to stop arguing :)
MQ2: Think of it as Evolution in action.

MacroFiend
a grimling bloodguard
a grimling bloodguard
Posts: 662
Joined: Mon Jul 28, 2003 2:47 am

Post by MacroFiend » Thu Oct 16, 2003 8:00 pm

ROFL ... Plaz and I weren't arguing. He asked for a piece moved, so it was moved :)