Along with giving me these error logs, it says "Unknown Command: sm_opp" in console, and does nothing when the command is displayed. I ran PrintToChatAll() after each Format(), so I know the command is already being executed and properly cycling through every client in the server for each team, but for some reason it won't display the panel. The IsClientInGame() gets an client indexes from an array of everyone's stored userids, I suppose if a userid equals exactly 0, the index will return 0? Regardless, I have no clue why that would stop the entire command from completing.
PHP Code:
L 09/18/2014 - 22:59:31: [SM] Native "IsClientInGame" reported: Client index 0 is invalid L 09/18/2014 - 22:59:31: [SM] Displaying call stack trace for plugin "opp.smx": L 09/18/2014 - 22:59:31: [SM] [0] Line 73, G:\SourcePawn\sources\opp.sp::Command_OrderedPlayerPanel()
Spoiler
PHP Code:
/* Clear all array entries then refresh them OnClientPutInServer, this is the only time the array should theoretically be organized, clear the proper array entry OnClientDisconnect, when reading from the array to display the list on the panel, ignore 0 value entries (it means client is no longer in game, as thus entry should be ignored) */ /* https://wiki.alliedmods.net/Format_Class_Functions_%28SourceMod_Scripting%29#Advanced_Formatting will help with adding buffers to strings to always make them the same length */
#pragma semicolon 1
#define CLIENTLIMIT 16 /* Real player limit */ #define TEAM_SPC 1 #define TEAM_SUR 2 #define TEAM_INF 3 #define NAME_DRAW_LENGTH 17+1 /* Actual name size + null terminator */
#include <sourcemod> #include <smlib>
new Handle:hOrderedPlayerPanel = INVALID_HANDLE;
new String:sNameLine[5+NAME_DRAW_LENGTH] = "\n - "; /* Length of string itself + what can be added to it from a client's name */
new aPlayersToOrder[CLIENTLIMIT+1]; /* The extra 1 accounts for console, we skip the console index and go straight to valid clients */
new bool:bFirstPass = false; /* Used to determine whether any names have already been added to the large team-name strings */
public Plugin:myinfo = { name = "Ordered Player Panel", author = "Țειğяğωүη", description = "Shows a list of all connected players in the game ordered by the player's total time in server since connection (ordered by userid) on a neat panel.", version = "0.0.1", url = "http://www.badtediz.com" }
public APLRes:AskPluginLoad2(Handle:hPlugin, bool:bLateLoad, String:sError[], vErrorLength) { // Plugin checked for late loading and ensuring it can only be ran on L4D1 if(IsL4DGame() == false){ strcopy(sError, vErrorLength, "'Ordered Player Panel' was created for L4D1 only.");
return APLRes_Failure; }
return APLRes_Success; }
public OnPluginStart() { RegConsoleCmd("sm_opp", Command_OrderedPlayerPanel, "Initiates the panel for 60 seconds total, automatically shuts off if a drastic event happens (such as round ending).", FCVAR_PLUGIN); }
public Action:Command_OrderedPlayerPanel(vClient, vArgs) { /* Shows the panel to the player for a limited amount of time, definite time dependant on a few factors, in the case of the ordered players array state being changed faster than 0.5s, only allow it to update that fast */ new vWho = 0;
for(vWho = 1; vWho <= CLIENTLIMIT; vWho++) { /* Looping through all clients, getting their userid, storing that userid into an array */ if(IsClientInGame(vWho) == true) aPlayersToOrder[vWho] = GetClientUserId(vWho); }
SortIntegers(aPlayersToOrder, CLIENTLIMIT, Sort_Descending); /* Ordering player list so that it can be translated and further sorted into proper team string lists */
decl String:sName[NAME_DRAW_LENGTH]; /* Stringed name of each client added to the menu, 17 characters ensures clients with longer names will have the ends omitted so that the panel is always of uniform width */
/* Preparing the panel ready for display by declaring all the team string player lists */ decl String:sPlayersOrderSur[128]; decl String:sPlayersOrderInf[128]; decl String:sPlayersOrderSpc[256]; /* Double the length because double the amount of players may sit on this team */
/* Looping through the array, getting the userid from each index in the array (the array should already be ordered by this point), check for client in game and non-bot, if true search client team and assign them into a player's list string for the specified team (when drawing teamname objects in panel later on, these strings will be called and all the names in the respective player's list team string shown) */ for(new index = 1; index <= CLIENTLIMIT; index++){ vWho = GetClientOfUserId(aPlayersToOrder[index]);
//for(new vBufferLength = 0; strlen(sName)+1 < NAME_DRAW_LENGTH; vBufferLength++){ /* Should be replaced with a function that truncates the player's name to be a total of 17 characters long (string must be 18, to account for null terminator) */ // StrCat(sName, sizeof(sName), " "); //}
/* Finally, creating all the panel objects, then displaying itself to the client */ hOrderedPlayerPanel = CreatePanel();
/* Titles are already part of the team strings themselves, no need to include them here :) */ DrawPanelText(hOrderedPlayerPanel, "PLACEHOLDER"); DrawPanelText(hOrderedPlayerPanel, sPlayersOrderSur); DrawPanelText(hOrderedPlayerPanel, sPlayersOrderInf); DrawPanelText(hOrderedPlayerPanel, sPlayersOrderSpc); DrawPanelText(hOrderedPlayerPanel, " "); /* Without this, the spacing between the top of the panel is a line larger than the bottom (AFAIK, exactly 24 characters, the length the panel should always remain) */
If an error happens, the entire callback is aborted. This is how Sourcemod works. You need to account for these potential errors and appropriately stop these errors from occurring. For example, don't run a client index of 0 through IsClientInGame().