[TUTORIAL] Make a /kill [id] [message] custom RCON command
#1

This tutorial will talk you through making a /kill [id] [message] command that you can type in the RCON window.

I know many of you like having godlike powers, and that is why you script your own gamemodes. I'm the same way, that's why I sneak some cool commands into the RCON section so I don't even have to be in the game to be God :P


Alright, let's start. Whether you want a separate FS for this or you are adding this to your Gamemode, you can still follow this tutorial.

First, we will be using dcmd, because it's so easy to use and (apparently, I don't notice it) it's faster than strtok/strcmp. So we need these lines of code. Read the top of each block of code to find where it goes

Declarations (All the way at the top)
Код:
#define dcmd(%1,%2,%3) if (!strcmp((%3)[1], #%1, true, (%2)) && ((((%3)[(%2) + 1] == '\0') && (dcmd_%1(""))) || (((%3)[(%2) + 1] == ' ') && (dcmd_%1((%3)[(%2) + 2]))))) return 1

All the way at the bottom (It is a stock after all)

Код:
stock sscanf(string[], format[], {Float,_}:...)
{
	#if defined isnull
		if (isnull(string))
	#else
		if (string[0] == 0 || (string[0] == 1 && string[1] == 0))
	#endif
		{
			return format[0];
		}
	#pragma tabsize 4
	new
		formatPos = 0,
		stringPos = 0,
		paramPos = 2,
		paramCount = numargs(),
		delim = ' ';
	while (string[stringPos] && string[stringPos] <= ' ')
	{
		stringPos++;
	}
	while (paramPos < paramCount && string[stringPos])
	{
		switch (format[formatPos++])
		{
			case '\0':
			{
				return 0;
			}
			case 'i', 'd':
			{
				new
					neg = 1,
					num = 0,
					ch = string[stringPos];
				if (ch == '-')
				{
					neg = -1;
					ch = string[++stringPos];
				}
				do
				{
					stringPos++;
					if ('0' <= ch <= '9')
					{
						num = (num * 10) + (ch - '0');
					}
					else
					{
						return -1;
					}
				}
				while ((ch = string[stringPos]) > ' ' && ch != delim);
				setarg(paramPos, 0, num * neg);
			}
			case 'h', 'x':
			{
				new
					ch,
					num = 0;
				while ((ch = string[stringPos]) > ' ' && ch != delim)
				{
					switch (ch)
					{
						case 'x', 'X':
						{
							num = 0;
							continue;
						}
						case '0' .. '9':
						{
							num = (num << 4) | (ch - '0');
						}
						case 'a' .. 'f':
						{
							num = (num << 4) | (ch - ('a' - 10));
						}
						case 'A' .. 'F':
						{
							num = (num << 4) | (ch - ('A' - 10));
						}
						default:
						{
							return -1;
						}
					}
				}
				setarg(paramPos, 0, num);
			}
			case 'c':
			{
				setarg(paramPos, 0, string[stringPos++]);
			}
			case 'f':
			{
				setarg(paramPos, 0, _:floatstr(string[stringPos]));
			}
			case 'p':
			{
				delim = format[formatPos++];
				continue;
			}
			case '\'':
			{
				new
					end = formatPos - 1,
					ch;
				while ((ch = format[++end]) && ch != '\'') {}
				if (!ch)
				{
					return -1;
				}
				format[end] = '\0';
				if ((ch = strfind(string, format[formatPos], false, stringPos)) == -1)
				{
					if (format[end + 1])
					{
						return -1;
					}
					return 0;
				}
				format[end] = '\'';
				stringPos = ch + (end - formatPos);
				formatPos = end + 1;
			}
			case 'u':
			{
				new
					end = stringPos - 1,
					id = 0,
					bool:num = true,
					ch;
				while ((ch = string[++end]) && ch != delim)
				{
					if (num)
					{
						if ('0' <= ch <= '9')
						{
							id = (id * 10) + (ch - '0');
						}
						else
						{
							num = false;
						}
					}
				}
				if (num && IsPlayerConnected(id))
				{
					setarg(paramPos, 0, id);
				}
				else
				{
					#if !defined foreach
						#define foreach(%1,%2) for (new %2 = 0; %2 < MAX_PLAYERS; %2++) if (IsPlayerConnected(%2))
						#define __SSCANF_FOREACH__
					#endif
					string[end] = '\0';
					num = false;
					new
						name[MAX_PLAYER_NAME];
					id = end - stringPos;
					foreach (Player, playerid)
					{
						GetPlayerName(playerid, name, sizeof (name));
						if (!strcmp(name, string[stringPos], true, id))
						{
							setarg(paramPos, 0, playerid);
							num = true;
							break;
						}
					}
					if (!num)
					{
						setarg(paramPos, 0, INVALID_PLAYER_ID);
					}
					string[end] = ch;
					#if defined __SSCANF_FOREACH__
						#undef foreach
						#undef __SSCANF_FOREACH__
					#endif
				}
				stringPos = end;
			}
			case 's', 'z':
			{
				new
					i = 0,
					ch;
				if (format[formatPos])
				{
					while ((ch = string[stringPos++]) && ch != delim)
					{
						setarg(paramPos, i++, ch);
					}
					if (!i)
					{
						return -1;
					}
				}
				else
				{
					while ((ch = string[stringPos++]))
					{
						setarg(paramPos, i++, ch);
					}
				}
				stringPos--;
				setarg(paramPos, i, '\0');
			}
			default:
			{
				continue;
			}
		}
		while (string[stringPos] && string[stringPos] != delim && string[stringPos] > ' ')
		{
			stringPos++;
		}
		while (string[stringPos] && (string[stringPos] == delim || string[stringPos] <= ' '))
		{
			stringPos++;
		}
		paramPos++;
	}
	do
	{
		if ((delim = format[formatPos++]) > ' ')
		{
			if (delim == '\'')
			{
				while ((delim = format[formatPos++]) && delim != '\'') {}
			}
			else if (delim != 'z')
			{
				return delim;
			}
		}
	}
	while (delim > ' ');
	return 0;
}
Now we have gotten dcmd declaration and stock out the way, we can move on. What's that? You don't understand? Don't worry, you won't need to understand it, that's why it was written. By a very clever person.

Alright, now comes the proper code we should understand:

OnRconCommand(cmd[])
Код:
dcmd(kill,4,cmd);
Explanation: The first argument is the command string we will use, second argument is how long the first argument is (I can see you counting the letters, yes, you), and the third is the variable that the command uses (So we are writing it to the variable cmd).

Anywhere, just not in any functions (Best place is under InRconCommand)
Код:
dcmd_kill(params[])
{
	new playerToKill, message[256];
	if(sscanf(params, "uz", playerToKill, message))
	{
	  print("Usage: /kill [id] [message]");
	}
	else
	{
 		SetPlayerHealth(playerToKill, 0.0);
  		GameTextForPlayer(playerToKill, message, 5000, 3);
		printf("[Admin Command (rcon)] [/kill] Rcon admin killed %s", PlayerName(playerToKill));
	}

	return 1;
}
Testing: Start up your gamemode server side. If it's an FS make sure it's in your ini. Now bring up your rcon to your server and type in /kill [id] [message] (Where [id] is the Player's ID and [message] is the message you want to give them) For Eg. /kill 1 God raped you (This will kill player ID 1 and will say on their screen "God raped you")

And that's that, we are done

Here's a link to dcmd: https://sampwiki.blast.hk/wiki/Fast_Commands
Reply
#2

Nice tutorial!
God raped you rofl
Reply
#3

Not bad, i did something similar some time ago.
Reply


Forum Jump:


Users browsing this thread: