The reason your members aren't showing up is likely due to how MySQL caches and String Concatenation behave in PAWN when buffers are mismanaged.
The "Ghost" Logic Bugs
The szDialog Confusion: In your original code, you used szDialog inside the loop but declared szDialog2 outside. If szDialog wasn't properly initialized or was too small, strcat(szDialog2, szDialog) would append empty or garbage data.
The Members Variable: You declared new Members; but never initialized it to 0. In some compiler versions, uninitialized locals can contain random "garbage" values from the stack. If Members started at a huge number, Selected[playerid][Members] would cause a memory out-of-bounds error, potentially crashing the script before it reached the dialog.
Buffer Overflow: With 50 members, your szDialog2[1024] was likely hitting its limit. When a string in PAWN exceeds its size during a format or strcat, it can null-terminate prematurely or cause the script to bail out.
The Fixed Logic
Here is the corrected logic. I have also moved the variables to be more memory-efficient and added an explicit initialization for the counter.
Code snippet
case 1:
{
// Use a static buffer to prevent stack exhaustion
static szBigDialog[3000];
new query[128], rows;
format(query, sizeof(query), "SELECT `Username`, `ClanRank`, `ClanWarns`, `ClanDays` FROM `users` WHERE `Clan` = '%d' ORDER BY `ClanRank` DESC LIMIT 50", PlayerInfo[playerid][pClan]);
new Cache:result = mysql_query(SQL, query);
cache_get_row_count(rows);
// Reset the buffer and the member counter
szBigDialog[0] = EOS;
strcat(szBigDialog, "#. Name\tRank\tClan Warns\tClan Days\n");
if(rows == 0) {
strcat(szBigDialog, " \tNo members found\t \t ");
} else {
new tempName[MAX_PLAYER_NAME], tempRank, tempWarns, tempDays;
new rowEntry[128];
for(new i = 0; i < rows; i++)
{
// Extracting data correctly
cache_get_value_name(i, "Username", tempName, sizeof(tempName));
cache_get_value_name_int(i, "ClanRank", tempRank);
cache_get_value_name_int(i, "ClanWarns", tempWarns);
cache_get_value_name_int(i, "ClanDays", tempDays);
// Store name for the OnDialogResponse selection
format(Selected[playerid][i], MAX_PLAYER_NAME, tempName);
// Build the row
format(rowEntry, sizeof(rowEntry), "%d. %s\t%d\t%d/3\t%d\n", i + 1, tempName, tempRank, tempWarns, tempDays);
// Append to the big string
strcat(szBigDialog, rowEntry);
}
}
cache_delete(result);
ShowPlayerDialog(playerid, DIALOG_CLAN_MEMBERS, DIALOG_STYLE_TABLIST_HEADERS, "Clan members", szBigDialog, "Select", "Back");
}
Why this version works:
Initialization: szBigDialog[0] = EOS ensures you aren't appending to old data left in memory.
Safety: Using rows directly from cache_get_row_count ensures the loop only runs exactly as many times as there are results.
Proper Indices: Using i as the index for Selected[playerid][i] ensures that the row number in the dialog matches the ID in your array perfectly.
Column Names: Ensure your SQL column names (Username, ClanRank, etc.) match your database exactly. MySQL is case-sensitive on some Linux distributions.
A Note on Selected[playerid]
Make sure your Selected array is large enough to hold the names! It should be defined globally like this: new Selected[MAX_PLAYERS][50][MAX_PLAYER_NAME];
If it’s defined as [MAX_PLAYERS][MAX_PLAYER_NAME], you are trying to store 50 names into a single string slot, which will overwrite the previous name every time.
Would you like me to check how you've defined the Selected variable to make sure it can handle 50 members?