NetBattle 1.0.5 Server Scripting FAQ by MasamuneXGP and Bayleef00 SECTION 0: INTRODUCTION ============================================= The Server Scripting feature has been refined and upgraded from 0.9.0. The script executes lines one by one, performing checks and commands to customize the server to the admin's taste. This FAQ will instruct you how to use it. Please note that this feature may still have some bugs in it. SECTION 1: EVENTS ============================================= The basic blocks of code are encased in Events. These blocks will execute when the Event triggers. To trigger the code BEFORE the event occurs, put a "-" before the event name. To trigger AFTER, put a "+". Here is the basic syntax: Code 1: ----------------------------- Event {-|+}[EventName] [Code] EndEvent ----------------------------- The valid entries for [EventName] are in Chart 1. Following them is a brief description of the event. Chart 1: Event Names ----------------------------- Event Name | Discription ServerStartup | Triggers when the server opens. NewMessage | Triggers when any new message is added to the Server text box. ChatMessage | Triggers when a chat message is recieved PlayerSignOn | Triggers when a player signs on PlayerSignOff | Triggers when a player signs off ChallengeIssued | Triggers when a Challenge is issued. BattleBegin | Triggers when a battle begins BattleOver | Triggers when a battle ends PlayerKick | Triggers when a player is kicked PlayerBan | Triggers when a player is banned PlayerAway | Triggers when a player enters Away state TeamChange | Triggers when a player changes teams Timer | Will be discussed later ----------------------------- So, here's an example of how it should look: Example 1 ----------------------------- Event +PlayerSignOn [Code] EndEvent ----------------------------- In this example, [Code] will execute every time a new player signs on, and it will execute after the sign on process is complete. So what kind of stuff can be put in [Code]? Let's take a look. SECTION 2: COMMANDS ============================================= Commands complete various tasks when you execute them. However, most commands require certain information, called Arguments. In List 1, the command is shown as it is to be written, with the required arguments following it. On the next line is a description. The arguments preceded by a "#" indicate a numerical value. Those preceded by a "$" indicate text. Those preceded by a "!" indicate that either text or a number can be used. And lastly, those preceded by a "@" indicate a constant. Arguments are delimited by commas. Text must ALWAYS be in quotes. List 1: Commands ----------------------------- /? !val ^^^Shows the value of !val in the Server text box. /Clear ^^^Clears the Server text box /SendPM #PNum, $Message ^^^Sends the text in $Message to only the player with the number #PNum. Note that this DOES NOT use the PM Window (It was named before PMs were implemented). /SendAll $Message ^^^Sends the text in $Message to all connected players. /Kick #PNum ^^^Disconnects player #PNum. /IPBan $Message ^^^Bans the IP specified in $Message. /SIDBan #PNum ^^^Disconnects player #PNum and adds his/her SID to the banned SID list. /Run $Path ^^^Runs a the program located at $Path /Ranks #X Copy User Ranking info from Rank 1 to Rank X (Maximum of 25) to string $Champs. /Usage #X Copy Pokemon usage info from Rank 1 to Rank X (Maximum of 40) to string $Used. /SaveValue $Key, !Val ^^^Saves a value to the Windows Registry. Advanced users can use this to extend the script's power. Keys are saved to the Visual Basic SaveSetting directory under /NetBattle/Script Values/[$Key] /SetPlayerInfo #PNum, @Info, !NewVal ^^^Sets the specified player's information as !NewVal. Only certain values can be set. A list of valid @Info values will be provided later. /Set !var, !val ^^^Will be discussed later. /Unset !var ^^^Will be discussed later. /Inc #var, #num ^^^Will be discussed later. /SaveLog ^^^Saves the server log. (Only usable if Logging is enabled) /StopEvent ^^^Stops the current event from taking place. Will be discussed in detail later. /Exit ^^^Halts the script. Will be discussed in detail later. ----------------------------- Let's try adding one if these commands to our previous example. This script will trigger directly after a player's sign on, and will send this humorous message to everyone. Example 2 ----------------------------- Event +PlayerSignOn /SendAll "Everyone point and laugh at the new player!" EndEvent ----------------------------- In addition to being used in scripts, commands can also be executed immediately by entering them in the server chat box. SECTION 3: VARIABLES ============================================= Most times, you will not want to enter an actual value for a command's argument. This is because you may desire different arguments under different situations. This is the purpose of variables. Variable are place markers that store information to be used in various places. Variables are created with the /Set command. As seen in List 1, the /Set command has 2 arguments: !var and !val. The first argument is special in that it CANNOT be a simple numerical or text value. It must be a variable. If the variable referred to does not yet exist, the /Set command will create it for you. Either way, the value of !val will then be stored in this variable. This argument may be omitted, in which case 0 or "" will be assumed, depending on the variable's type. !val may also be a variable, if you wish to set one variable equal to another. There are two types of variables: Text variables and Number variables. When refering to a Text variable, put a "$" before its name. For a number variable, put a "#" before its name. Variable names must consist of only letters. You may observe variables and their values in the Variables tab of the Script Window. There are also three special variables: #Source, #Target, and $Message. These variables always exist, even though they are not in the Variables tab. They change automatically depending on the event. Chart 2 lists the values for these variables for each event. If a variable is listed as N/A, that variable is equal to 0 or "" during that event. Chart 2: Special Variables ---------------------------------------------------------- Event Name | #Source | #Target | $Message ServerStartup | N/A | N/A | N/A NewMessage | N/A | N/A |[Message Added] ChatMessage | [Sender] | N/A |[Chat Message] PlayerSignOn |[Player Num]| N/A | N/A PlayerSignOff |[Player Num]| N/A | N/A ChallengeIssued |[Challenger]|[Challengee]| N/A BattleBegin | [Player 1] | [Player 2] | N/A BattleOver | [Winner] | [Loser] |{"TIE"|"WIN"} PlayerKick | [Kicker] |[Kicked Num]| N/A PlayerBan | [Banner] |[Banned Num]| N/A PlayerAway |[Player Num]| N/A | N/A TeamChange |[Player Num]| N/A | N/A Timer | N/A | N/A | N/A ----------------------------------------------------------- So, let's once again add a bit to our example. The script in example 3 uses the /SendPM instead of the /SendAll message to send the message only to new player. However, if you recall, /SendPM has two arguements. The second argument is the message to be sent, that one's easy enough, but the first argument is the Player Number of the player to send it to. By consulting Chart 2, we see that the Player Number we need is stored in the variable #Source. So, we use #Source for the first argument, and our message for the second. The end result is that when a new player signs on, the message "Welcome to the server!" will be sent to only that player. Example 3 ----------------------------- Event +PlayerSignOn /SendPM #Source, "Welcome to the server!" EndEvent ----------------------------- There are also to other commands that pertain to variables. /Unset destroys a variable from memory. This cannot be used on the special variables. /Inc is a bit more complicated. /Inc has two arguments; the first must be a variable, or more specifically, a number variable. The variable is increased by the amount in the second argument. If the second argument is omitted, 1 is assumed. To decrease a variable, simply use a negative number for the second argument. Variables provide for a lot of customization, but there's one more tool you'll need: SECTION 4: FUNCTIONS ============================================= Functions take various arguments and return a number or text value. Functions can be used in place of actual values for command arguments as well as other function arguments. As with variables, functions returning a number are preceded by a "#" and those returning text with a "$". List 2 lists all functions, with the arguments, if any, following them. On the next line is a description. List 2: Functions ----------------------------- #IsLoaded(#PNum) ^^^Returns 1 if Player PNum exists. Returns 0 otherwise. $Name(#PNum) ^^^Returns Player PNum's name. $Pokemon(#PokeNum) ^^^Returns the name of a Pokémon matching the number specified in #PokeNum #PNumber($PName) ^^^Returns the number of the player matching then name $PName. Returns 0 if no such player is connected. #HasPoke(#PNum, #PokeNum) ^^^Returns 1 if Player PNum has the Pokémon with the No. PokeNum in his/her team. Returns 0 otherwise. #HasPokeMove(#PNum, #PokeNum, #MoveNum) ^^^Returns 1 if Player PNum has the Pokémon with the No. PokeNum and having the move MoveNum in his/her team. Returns 0 otherwise. #GetTeamPoke(#PNum, #N) ^^^Returns the Pokédex number of a Pokémon in Player #PNum's team. Valid values for #N are 1 through 6. #GetPlayerInfo(#PNum, @Info) ^^^Returns the specified Player's information depending on the value of @Info. (Number only) @Info is a constant; valid values are as follows: AUTH (Authority - 0 = User, 1 = Mod, 2 = Admin) BWTH (Battling With - 0 if not battling) SPED (Player Speed) HIDE (Team Hidden - 0 = Hidden, 1 = Shown) WINS (Wins) LOSE (Losses) TIES (Ties) DISC (Disconnects) STAT (Supreme Points) $GetPlayerInfo(#PNum, @Info) ^^^Returns the specified Player's information depending on the value of @Info. (Text only) @Info is a constant; valid values are as follows: NAME (Name) IPAD (IP Address) PSID (Station ID) DNSA (DNS Address) EXTR (Extra Information) VERS (NetBattle Version Number) #GetCompat(#PNum, #CompatNum) ^^^Check a Player's team compatibility and returns a 1 or a 0, depending on #CompatNum. Valid values for #CompatNum are as follows: 0 - RBY w/ Trades 1 - GSC w/ Trades 2 - RBY w/o Trades 3 - GSC w/o Trades #LineNum ^^^Returns the number of lines of text in the main message box. #TrainersNum ^^^Returns the number of connected Players #SysTimer ^^^Returns the number of seconds past midnight. $Time ^^^Returns the current time in the form: HH:MM:SS AM/PM $Date ^^^Returns the current date in the form: MM/DD/YY $WeekDay ^^^Returns the current day of the week. $Month ^^^Returns the current month. #Rand(#UpperLimit, #LowerLimit) ^^^Returns a random integer between #LowerLimit and #UpperLimit, inclusive. If #LowerLimit is omitted, 0 is assumed. #RandPlayer ^^^Returns a random player number. Returns 0 if no players are connected. #GetValue($Key) ^^^Retrieves a number from the Windows Registry. An error occurs if the value is not a number. $GetValue($Key) ^^^Retrieves a number from the Windows Registry. If the value is a number, it is coverted to text. $Msg(#Index) ^^^Returns a Predefined Message, set in the Script Window on the Messages tab. #MaxUsers ^^^Returns the maximum number of players. #FloodTol ^^^Returns the server's flood tolerance. $WelcomeMsg ^^^Returns the server's welcome message. $Left($Text, #Number) ^^^Returns the specified number of characters from the left of the text. $Right($Text, #Number) ^^^Returns the specified number of characters from the right of the text. $Mid($Text, #Start, #Length) ^^^Returns a portion of the text $Text starting at the character specified in #Start as long as #Length characters. #IsIn($Text, $Check, #Case) ^^^Checks if $Check is located anywhere in $Text. If so, returns the number of characters into $Text that $Check is found. If not, returns 0. #Case specifies whether or not the check is case sensitive. 0=Not CS, 1=CS. If omitted, Not CS is assumed. #Len($Text) ^^^Returns the number of characters in the text. $Replace $SourceText, $Find, $Replace ^^^Searchs for the text $Find in $SourceText and replaces it with $Replace. Returns the result. $LCase($Text) ^^^Puts all the letters in $Text in lower case. $UCase($Text) ^^^Puts all the letters in $Text in upper case. $Chr(#Code) ^^^Returns the character specified by the ASCII code #Code. Valid values for #Code are 0 to 255. NOTE: $Chr(1) is reserved for system use. If you try to use it, it will be replaced with $Chr(2). Both are meaningless characters. #Asc($Character) ^^^Returns the ASCII code for the character. If the length of $Character is more than 1, the first character is used. $Str(#Number) ^^^Returns the specified number in text format. #Val($Text) ^^^Returns the numbers in a text statement in number format. ----------------------------- Functions provide for a high level of customization. Let's once again add to our previous example. This time we may perform functions to change the message depending on the user. Note that the amperstand ("&") is used to join two text values. Example 4 ----------------------------- Event +PlayerSignOn /SendPM #Source, "Welcome to the server, " & $Name(#Source) & "!" /SendPM #Source, "Your name in upper case is " & $UCase($Name(#Source)) & "." /SendPM #Source, "Your lucky number is " & $Str(#Rand(9999, 1000)) & "." EndEvent ----------------------------- Alright, let's go through this one line by line. This script sends 3 messages to the new player. If you remember from our previous example, #Source contains the player number for the new player. Let's look at the first /SendPM. In it you will see the $Name function, and from List 2, you see that this function returns the name of the player with the number given in the argument. Therefore, this function returns the name of the new player. The ampersands join the name with the rest of the message. The second /SendPM is a bit more complicated. It has a function within a function. There's the $Name function, we know what that does already. But that function is within a another function, $UCase. From List 2, we see that $UCase takes its argument and returns it in all caps. So, as the rest of the message implies, it returns the user's name in upper case. The third /SendPM also contains a function within a function. This time the innermost function is #Rand, which from List 2, we see returns a random number with its two arguments as bounds. However, this function is a number function, and cannot be joined to a text message as is. The return value of #Rand must first be converted to text, which is what the $Str function does. So then, let's see the results. Say I connect to a server with this script under my usual name, MasamuneXGP. Here's what I would see: Flood count is set to 5 Your team's power is: 77% Welcome to the server, MasamuneXGP! Your name in upper case is MASAMUNEXGP. Your lucky number is 8157. Of course, the "lucky number" would be different each time, but you get the idea. However, there are some commands that you may wish to execute only under certain conditions. The way to do this is by using... SECTION 5: IF-ELSE-ENDIF ============================================= These special commands are used to check a condition, and execute code based on the validity or falsehood of the condition. The basic syntax is: Code 2: ----------------------------- If [Value1] [Operator] [Value2] [Commands] Else [Other Commands] EndIf ----------------------------- Where [Operator] is, a conditional method should be placed. Valid methods are: Chart 3: Operators ----------------------------- = | Equal to == | Equal to (case sensitive when checking Text) <> | Not equal to > | Greater than < | Less than >= | Greater than or equal to <= | Less than or equal to ----------------------------- If the check is true, the commands directly after If statement will execute. If it is false, the commands directly after the Else statement will execute. If the Else statement is omitted and the check is false, execution will jump to directly after the EndIf statement. So then, let's some more code to our example. This one will check the new player's team for Mewtwo, and if it contains one, the player will be booted. Note that this takes place in a different Event, so that the check will take place BEFORE the user finishes signing on. Example 4 ----------------------------- Event -PlayerSignOn If #HasPoke(#Source, 150) = 1 /SendPM #Source, "Mewtwo is not allowed here!" /Kick #Source Else /SendPM #Source, "Your team is valid and ready for battling!" EndIf End Event Event +PlayerSignOn /SendPM #Source, "Welcome to the server, " & $Name(#Source) & "!" /SendPM #Source, "Your name in upper case is " & $UCase($Name(#Source)) & "." /SendPM #Source, "Your lucky number is " & $Str(#Rand(9999, 1000)) & "." EndEvent ----------------------------- Let's take the If statement and go through it. It begins with the word "If" to show that it's a condition check. The next statement is a function, #HasPoke. It will return 1 if player #Source has Pokemon number 150, aka Mewtwo, in his or her team. So then, once this function is evaluated, it will be replaced with a 0 or a 1 depending on the result, and we will be left with "If 1 = 1" or "If 0 = 1". In the first case, it will be true, and the code directly after the If statement will executed, sending the warning message and kicking the player. If it returns false, the other message will be sent and the player will be allowed to sign on, trigging the next event. You may also check more than one condition in a single If statement by using the AND, OR, XOR, and EQV statements. Their functions are listed in Chart 4. Chart 4: ----------------------------- AND | Returns True if both conditions are true OR | Returns True if either of the conditions are true XOR | Returns True if one of the conditions is true and the other is false. EQV | Returns True if both conditions are true or both are false. ----------------------------- You may string as many conditions as you like together using these statements. Let's make a small change to our example. Lets say you want to disallow Mewtwo only from regular users, and let Mods and Admins use Mewtwo if they like. The following script would do just that. Example 5 ----------------------------- Event -PlayerSignOn If #HasPoke(#Source, 150) = 1 AND #GetPlayerInfo(#Source, AUTH) = 0 /SendPM #Source, "Mewtwo is not allowed here!" /Kick #Source Else /SendPM #Source, "Your team is valid and ready for battling!" EndIf End Event ----------------------------- Now the If statement checks two things. It checks to make sure that the user's team has a Mewtwo, and it checks if the user's authority level is 0 (normal user). If BOTH of these conditions are true, the /Kick activates. Note that the Else statement is NOT necessary. You may leave it out entirely if you want nothing to be done in the event that the condition is false. SECTION 6: OTHER STUFF ============================================= This second contains a few other tid-bits that you might find helpful. ***The Timer Event*** One extra event that's different from the others is the Timer event. This event is not triggered by an action like the other events are, but rather it is triggered automatically with a set interval. Use the following syntax when beginning a Timer event. Code 3: ----------------------------- Event Timer [Interval] [Code] EndEvent ----------------------------- As you can see, this statement lacks a + or - and also has an extra arguement: the timer's interval. The interval may be any integer between 1 (1 second) and 86400 (86400 seconds, exactly 24 hours). For instance, to create a timer event that will execute every five seconds, you would type "Event Timer 5" as the first line. The code within the event would then execute every five seconds until the server shuts down. ***Predefined Messages*** The Messages tab on the script window allows you to create Predefined Messages. PDMs are useful for sending messages that you will be sending on many different occasions, so you only have to type it once. Note that all PDMs MUST BE IN QUOTES to use; they are just like a text variable. The difference however is that you may use any functions you like in your PDMs, so you can allow for personalization depending on the scenario. To retrieve a PDM from the script, use the $Msg function. ***/Exit*** One of the commands not previously explained is the /Exit command. When this command is executed, the script halts prematurely, and no further lines are processed. This is useful for situations were further processing would be pointless. For instance, let's say you wanted to ban both Mewtwo and Lugia from your server. It would look like this. Example 6 ----------------------------- Event -PlayerSignOn If #HasPoke(#Source, 150) = 1 /SendPM #Source, "Mewtwo is not allowed here!" /Kick #Source /Exit EndIf If #HasPoke(#Source, 249) = 1 /SendPM #Source, "Lugia is not allowed here!" /Kick #Source EndIf /SendPM #Source, "Your team is valid and ready for battling!" EndIf End Event ----------------------------- Note that the /Exit command will execute if the player has a Mewtwo. This because, since the player will be kicked anyway, it would be pointless to check if the player had a Lugia. ***/StopEvent*** Another useful command is the /StopEvent command. This command stops the event from taking place. The /StopEvent command is only valid in certain events. They are: List 3: /StopEvent events ----------------------------- -NewMessage -ChatMessage -PlayerAway -PlayerKick -PlayerBan -ChallengeIssued ----------------------------- Note that this only works if the command is in a MINUS event, meaning an event that triggers before the action takes place. When the /StopEvent triggers, the action that triggered the event will be cancelled. This can be useful for many things. For example, if you wanted to shut down your server but didn't want to interrupt someone's battle, you wouldn't want people starting any NEW battles. Therefore a simple /StopEvent in the -ChallengeIssued event would prevent any challenges from being sent. ***Player Arrays*** Sometimes it becomes necessary to have a different variable for each connected player. To do this, you use a player array. Create them with the /SetPA command: Code 4: ----------------------------- /SetPA {#|$}ArrayName ----------------------------- Set the individual variables with the regular /Set command. Code 5: ----------------------------- /Set #ArrayName(#PNum), #Value ----------------------------- When a player signs off the variable assigned to that player is automatically cleared. When a new player signs on, a new variable is automatically created for that player. Example 6 ----------------------------- Event +PlayerSignOn /Set $CapNam(#Source), $UCase($Name(#Source)) End Event ----------------------------- The above script would keep track of each player's name in Upper Case. The values for all player arrays can be viewed in the script window. ***Markers and GoTo*** Markers are used to set a certain spot in your script to jump to. Do set a marker, begin a line with a colon (":") and type a word after it to use as the Marker's name. To jump to a specific marker, use the GoTo statement. Example 7: ----------------------------- Event +ChatMessage If $Message = "Countdown" /Set #X, 5 :Loop /? $Str(#X) /Inc #X, -1 If #X <> 0 GoTo Loop EndIf /? "Blast Off!!" EndIf End Event ----------------------------- This example would display the text following text message whenever the word "Countdown" was received: 5 4 3 2 1 Blast Off!! As you can see, the three lines between the Marker and the GoTo statement would continue to execute until the condition "#X <> 0" was no longer true. Of course, in this particular example, it would probably be easier just to say /? "5" all the way down to /? "1", but you get the idea. SECTION 7: CLOSING REMARKS ============================================= Keep in mind that this is a very beta scripting module. There are probably a few bugs in it here and there, and there is still a lot of functionality to be added in the future. However, I think this is still enough to have fun with. --MasamuneXGP, Bayleef00