08.07.2012, 18:38
(
Последний раз редактировалось Kwarde; 08.07.2012 в 20:18.
Причина: Forgot one char in the title ('filterscript' instead of 'filterscripts')
)
Hello. I'm gonna make a small tutorial -and final script- of a filterscript that (un/re)loads all your filterscripts (NOTE: These must be defined in an array in one filterscript).
Why would this be usefull?
Well, if you have loadfs of filterscripts, it could be usefull to put all of these filterscripts in a seperate directory in your filterscripts folder, and put one filterscript named 'fs' (or something like that) that have to be (un/re)loaded only in order to reload all your filterscripts.
Also, this describes some functions people might not understand. It explains the next functions/things:
while(), format(), SendRconCommand() = obvious, double/single arrays, 'i'=>'index'
Example
/SAMP/filterscripts:
* /fscripts
* fs.pwn
* fs.amx
/SAMP/filterscripts/fscripts:
* debug.pwn
* debug.amx
* ls_elevator.amx
* npc_record.amx
* NPCTest.amx
* NPCTest.pwn
* UIC.amx
* UIC.pwn
(etc.)
In order to load all the filterscripts in the 'filterscripts/fscripts' map, you have to load the 'fs.amx' only. You can (probably) use a plugin to even get all the files in /fscripts and automatically load all the .amx files, but I'll use a_samp (and eventually zcmd) only to make it easier.
How is it gonna work?
The idea is 'easy as hell'. It's just an array containing all the .amx filenames (without .amx). When 'fs.amx' is initialising (OnFilterScriptInit), it'll loop through all those filenames in the array and load all those filterscripts. When the filterscript is exitting (OnFilterScriptExit), it'll do the same, but then using the RCON command 'unloadfs' instead of 'loadfs' (small difference). You can eventually create an ingame command that does the same again, but then with 'reloadfs'.
How to create this array
You have to create a double array: new filterScripts[][] and NOT a single one (new filterScripts[]). You musn't use a single array, because the loop won't loop through those names then, but through all the names character by character (and then adding the previous characters too). Examples:
new filterScripts[] = {"fs","gm","debug"};
When you use this one, and you loop through the array, the system will try to load the filterscripts like this (or atleast similar to this):
loadfs s
loadfs fs
loadfs m
loadfs gm
loadfs g
loadfs ug
loadfs bug
loadfs ebug
loadfs debug
This will give alot "Failed to load filterscript" errors in the client, and it just is useless. When using a double array, this won't happen.
The example filterscripts in this script will be the next scripts: debug, ls_elevator, npc_record, NPCTest, UIC
This array will look like this:
How to create this loop
I'll be using the function 'while()'. This function will run untill the statement within the brackets is 'false'. So we'll create an "index" (new index;). The standard value of this index is '0', since it hasn't got a value. We will combine this with the "sizeof" function; it checks the size of an array. The array I am using has got 5 strings, so sizeof(filterScripts); will return 5. This means we'll be checking if the value of index is beneath 5. While it's beneath 5, it'll be returned as true, so the loop will continue. When it's 5 (or higher), the index is not beneath 5 and it will return FALSE, which will stop the loop. After one loop, we'll be increasing the "index".
So, how to do this? I'll show you:
So this loop is done, and it works.
How to unload, reload of load the filterscript
The function "SendRconCommand" is required for this. This function can send RCON command just like in the RCON console or ingame (ingame = command "/rcon {rcon_command}" - in the console: "{rcon_command}").
An example to load the filterscript "fs.amx": SendRconCommand("loadfs fs");. If this 'fs.amx' is inside the 'fscripts' folder (inside the 'filterscripts'), it must look like this: SendRconCommand("loadfs fscripts/fs");.
If you're very new to scripting, you may not know that you can't just use the value of the array in the command directly. You must first "format" it. We'll need a string for this, and the format function. This is very basic so I'll just give the example. I'm using a string with a length of 50. In order to get the current string name from the array in the loop, you must use the index we created (so yes, it has two usefull functions this "index")
In order to use this string in the SendRconCommand function, you must replace the quotes and the text with the "loadFsString": SendRconCommand(loadFsString);
You mostly see loops using 'i'. If you didn't understand why it was 'i' before, you know it now: It stands for "index" (Well, atleast that's what I guessed. Please correct me if I'm wrong).
Know our entire script looks like this:
So, all the strings in "filterScripts" will be loaded, IF this 'fs.amx' is loaded, and if the next files exist:
/filterscripts/fscripts/debug.amx
/filterscripts/fscripts/ls_elevator.amx
/filterscripts/fscripts/npc_record.amx
/filterscripts/fscripts/NPCTest.amx
/filterscripts/fscripts/UIC.amx
What else?
Nothing really. In order to do the same with unloading and reloading, just change the "loadfs" in the format() function to "unloadfs" or "reloadfs". I recommend to put this "unloadfs" in OnFilterScriptExit(), and the 'reloadfs' eventually in a command.
A full example, as a working filterscript (unless if you don't have these filterscripts in the 'fscripts' directory ^^
NOTE: I am used to do the 'index++' before the format() and SendRconCommand() functions. This would mean that 'debug' wouldn't be loaded, but this is not true! Because instead of leaving the 'index' value on '0', I gave it '-1' so it'll be '0' on the first loop (Counting in scripting starts at 0 instead of 1)
I hope this will be usefull for atleast one person. I'd like to get feedbacks, with eventually tips, corrections and compliments ^^
Kind regards,
Kwarde
p.s.
To show that it really worked, I created temporarly a custom 'SendRconCommand' that puts the input into a file. Eg. if 'loadfs debug' was called, it was saved in a file. Here's the file's content:
Why would this be usefull?
Well, if you have loadfs of filterscripts, it could be usefull to put all of these filterscripts in a seperate directory in your filterscripts folder, and put one filterscript named 'fs' (or something like that) that have to be (un/re)loaded only in order to reload all your filterscripts.
Also, this describes some functions people might not understand. It explains the next functions/things:
while(), format(), SendRconCommand() = obvious, double/single arrays, 'i'=>'index'
Example
/SAMP/filterscripts:
* /fscripts
* fs.pwn
* fs.amx
/SAMP/filterscripts/fscripts:
* debug.pwn
* debug.amx
* ls_elevator.amx
* npc_record.amx
* NPCTest.amx
* NPCTest.pwn
* UIC.amx
* UIC.pwn
(etc.)
In order to load all the filterscripts in the 'filterscripts/fscripts' map, you have to load the 'fs.amx' only. You can (probably) use a plugin to even get all the files in /fscripts and automatically load all the .amx files, but I'll use a_samp (and eventually zcmd) only to make it easier.
How is it gonna work?
The idea is 'easy as hell'. It's just an array containing all the .amx filenames (without .amx). When 'fs.amx' is initialising (OnFilterScriptInit), it'll loop through all those filenames in the array and load all those filterscripts. When the filterscript is exitting (OnFilterScriptExit), it'll do the same, but then using the RCON command 'unloadfs' instead of 'loadfs' (small difference). You can eventually create an ingame command that does the same again, but then with 'reloadfs'.
How to create this array
You have to create a double array: new filterScripts[][] and NOT a single one (new filterScripts[]). You musn't use a single array, because the loop won't loop through those names then, but through all the names character by character (and then adding the previous characters too). Examples:
new filterScripts[] = {"fs","gm","debug"};
When you use this one, and you loop through the array, the system will try to load the filterscripts like this (or atleast similar to this):
loadfs s
loadfs fs
loadfs m
loadfs gm
loadfs g
loadfs ug
loadfs bug
loadfs ebug
loadfs debug
This will give alot "Failed to load filterscript" errors in the client, and it just is useless. When using a double array, this won't happen.
The example filterscripts in this script will be the next scripts: debug, ls_elevator, npc_record, NPCTest, UIC
This array will look like this:
pawn Код:
new filterScripts[][] = {
"debug",
"ls_elevator",
"npc_record",
"NPCTest",
"UIC"
};
I'll be using the function 'while()'. This function will run untill the statement within the brackets is 'false'. So we'll create an "index" (new index;). The standard value of this index is '0', since it hasn't got a value. We will combine this with the "sizeof" function; it checks the size of an array. The array I am using has got 5 strings, so sizeof(filterScripts); will return 5. This means we'll be checking if the value of index is beneath 5. While it's beneath 5, it'll be returned as true, so the loop will continue. When it's 5 (or higher), the index is not beneath 5 and it will return FALSE, which will stop the loop. After one loop, we'll be increasing the "index".
So, how to do this? I'll show you:
pawn Код:
new index; //The 'index', value = 0
while (index < sizeof(filterScripts)) //While 'index' < '5';
{
index++; //Increase 'index' by 1. Once it reached 5, it won't be continued next time.
}
How to unload, reload of load the filterscript
The function "SendRconCommand" is required for this. This function can send RCON command just like in the RCON console or ingame (ingame = command "/rcon {rcon_command}" - in the console: "{rcon_command}").
An example to load the filterscript "fs.amx": SendRconCommand("loadfs fs");. If this 'fs.amx' is inside the 'fscripts' folder (inside the 'filterscripts'), it must look like this: SendRconCommand("loadfs fscripts/fs");.
If you're very new to scripting, you may not know that you can't just use the value of the array in the command directly. You must first "format" it. We'll need a string for this, and the format function. This is very basic so I'll just give the example. I'm using a string with a length of 50. In order to get the current string name from the array in the loop, you must use the index we created (so yes, it has two usefull functions this "index")
pawn Код:
new loadFsString[50];
format (loadFsString, 50, "loadfs fscript/%s", filterScripts[index]);
You mostly see loops using 'i'. If you didn't understand why it was 'i' before, you know it now: It stands for "index" (Well, atleast that's what I guessed. Please correct me if I'm wrong).
Know our entire script looks like this:
pawn Код:
#include <a_samp> //Didn't mention it before, but this is just something basic. The only required include for this script
new filterScripts[][] = {
"debug",
"ls_elevator",
"npc_record",
"NPCTest",
"UIC"
};
//You can't just use this script nothing and everywhere. This should be in "public OnFilterScriptInit()", so all the 'filterScripts' will be loaded when the 'fs.amx' is loaded.
new index, loadFsString[50];
while (index < sizeof(filterScripts))
{
format (loadFsString, 50, "loadfs fscript/%s", filterScripts[index]);
SendRconCommand(loadFsString);
index++; //Don't put this before the SendRconCommand and the format() function, otherwise 'debug' won't be loaded!
}
/filterscripts/fscripts/debug.amx
/filterscripts/fscripts/ls_elevator.amx
/filterscripts/fscripts/npc_record.amx
/filterscripts/fscripts/NPCTest.amx
/filterscripts/fscripts/UIC.amx
What else?
Nothing really. In order to do the same with unloading and reloading, just change the "loadfs" in the format() function to "unloadfs" or "reloadfs". I recommend to put this "unloadfs" in OnFilterScriptExit(), and the 'reloadfs' eventually in a command.
A full example, as a working filterscript (unless if you don't have these filterscripts in the 'fscripts' directory ^^
pawn Код:
#define FILTERSCRIPT
#include <a_samp>
#include <zcmd>
new filterScripts[][] = {
"debug",
"ls_elevator",
"npc_record",
"NPCTest",
"UIC"
};
public OnFilterScriptInit()
{
new loadFsStr[50], index = -1;
while (index <= sizeof(filterScripts))
{
index++;
format(loadFsStr, 50, "loadfs fscript/%s", filterScripts[index]);
SendRconCommand(loadFsStr);
}
return 1;
}
public OnFilterScriptExit()
{
new loadFsStr[50], index = -1;
while (index <= sizeof(filterScripts))
{
index++;
format(loadFsStr, 50, "unloadfs fscript/%s", filterScripts[index]);
SendRconCommand(loadFsStr);
}
return 1;
}
CMD:reloadfs(playerid, params[])
{
new loadFsStr[50], index = -1;
while (index < sizeof(filterScripts))
{
index++;
format(loadFsStr, 50, "reloadfs fscript/%s", filterScripts[index]);
SendRconCommand(loadFsStr);
}
SendClientMessage(playerid, -1, "{00FF00}Filterscripts reloaded");
return 1;
}
I hope this will be usefull for atleast one person. I'd like to get feedbacks, with eventually tips, corrections and compliments ^^
Kind regards,
Kwarde
p.s.
To show that it really worked, I created temporarly a custom 'SendRconCommand' that puts the input into a file. Eg. if 'loadfs debug' was called, it was saved in a file. Here's the file's content:
Код:
loadfs fscript/debug loadfs fscript/ls_elevator loadfs fscript/npc_record loadfs fscript/NPCTest loadfs fscript/UIC unloadfs fscript/debug unloadfs fscript/ls_elevator unloadfs fscript/npc_record unloadfs fscript/NPCTest unloadfs fscript/UIC