[Resource]-Torquescript Learners Guide-[WIP]

Author Topic: [Resource]-Torquescript Learners Guide-[WIP]  (Read 8381 times)

Torquescript Learners Guide

Hello there, chances are you've come to this topic to learn some Torquescript so you can make some basic add-ons for your favorite game, Blockland.  Well I'm here to do my absolute best to help you achieve that goal!
Let's begin, shall we?



Syntax
Syntax is sort of like grammar for programming languages, it is the correct way to form and position the lines of code you will be writing, such as always putting a period on the end of a sentence.  Torquescript has a very easy to learn, in my opinion, syntax.
[This section will be re-done]



Variables
Contrary to most programming languages, Torquescript does not require the usage of actually declaring variables, the first time the variable is used it will automatically be declared, what are variables exactly, might you ask.  A variable is a tool used to store information, the types are a string and to my best belief a byte.  A string is a variable that uses letters or a letter and number combination.  A byte is simply a number.  To set a variable you use the variable indicator, the variable name, an equals sign, and the value it should be set to, followed by a semicolon.  Here are some examples:

Code: [Select]
$Test = 1;
Code: [Select]
%Test = "Hello World";
Notice how one indicator is a percent sign and the other is a dollar sign?  If you did, good job.  The dollar sign represents a global variable, which will stay the same unless changed or the script is no longer being executed.  A percent sing indicates a local variable, which will only persist for the duration of the function it is being used in.  Also notice the "$Test" variable has no parenthesis, but the "%Test" does, the parenthesis are needed to declare anything that includes non-numerical characters.



Functions
Alright, so you've made it this far?  Good job, now let's learn the heart of any programming, functions.  Getting something done.  A function is an executable piece of code that can be called anytime to return a value or cause an event to happen.  Torque/Blockland already has pre-programmed functions that can be accessed, and modified.  But first why don't we learn how to create a function?  Here's an example:

Code: [Select]
function Test_This(%input)
{
return %input;
}

Okay, so let's get to understanding this code now, the "function" part is used to tell the engine that we are creating a new function, we then add a space and decide our name.  The name cannot start with anything besides a letter, and the entire name cannot contain spaces, you must use an underscore if you want to create a space.  We then use an opening parenthesis to start our arguments, we would put the name of any argument that we need in the function to run it, and seperate two using a comma.  After this we start a new line and use an opening bracket, without this you will get a syntax error, this bracket lets Torque know that you are beginning the function.  Inside this bracket we then use another new line and tab, the tab is used anytime after you use a bracket, we will learn more about this later.  Then put whatever the code is inside the white space you now have, using a new line anytime you start a new method.  Also notice what I've gone ahead and put in the function, "return %input;".  Let's break this down.  "Return" is used to end the function and return the value specified.  If we made %input equal to 1, and called the function, it would return the value 1.  Then the semicolon at the end of the line is used at the end of any method.  Then we use our closing bracket to end the function.

Now let's call our new function!

Code: [Select]
echo(Test_This(1));
Using this, you should get the number 1 returned and echoed to you, now, what is echo?  Echo is used to write the value inside of the parenthesis inside your console window, accessable by the tilde key.  You've made your first working function!  Also remember you can change the "1" inside the function calling to anything you want and it will echo it, but if you use anything besides numbers be sure to use parenthesis!



If-Then-Else Statements
Now let's get a little more in-depth.  If-Then-Else statements are used to determine if one thing is equal to another, and are extremely useful.  I'll be referring to them as if-statements for the sake of my fingers for the next part.  If-statements can be used in many ways, it's all based on what you are doing.  Let's see some examples:

Code: [Select]
function Test_This(%input, %check)
{
if(%input $= %check)
{
return "true";
}
else if(%input > %check)
{
return "greater than";
}
else if(%input < %check)
{
return "less than";
}
else
{
return "false";
}
}

Alright, let's get to it.  First you will see I started my function as usual, and created two variables to use.  Then I use if and an opening parenthesis to indicate me putting the parameters in.  I then put my variable name, condition, and the second variable name.  If the condition is met, it will execute the code inside the brackets of that if-statement, if not, it will go to the next statement and do the same.  The next statement is and "else if", meaning if the past if wasn't true, then see if this is.  The last was just an "else" statement, so if no other conditions were met, then the "else" will be called.  Now let's see something else:

Code: [Select]
function Test_This(%input, %check)
{
if(%input > %check || %check > %input)
return 1;
else if(%input $= %check && %check $= %input)
return 2;
}

Now this one is a bit more tight and easy to read, but it doesn't do the same thing as the last.  Notice how after the if-statements it doesn't have brackets, if the method you are calling after the if-statement is only one line, you don't need to use brackets.  You may also notice the || and the && signs, let's see what these mean.  || means "or", if this is true, OR, this is true, then the condition is met.  The && means "and", if this is true, AND, this is true, the condition is met.



This is only the very beginning of this resource, it will be expanded upon in the next two days greatly, if you have anything to contribute or want to be put in, please feel free to let me know, and if anyone is trying to learn, but needs one-on-one help, feel free to add me on Steam using the name in my profile





What's an If-Then
If (blah) Then is the most commonly used format in programming languages, so I refer to it as such.  Torque doesn't need "then" due to brackets



I'd say a lot of new scripters want to learn how to make server commands..


Client and Server Commands
Have you ever used commands such as, for example, "/buyDirt 50 500" etc.? Have you wondered how to make "slash commands"?
Before you can learn that, let us recap and discuss what a client and a server is. In Blockland, when someone is hosting a server, the Blockland server running on their computer is the Server. When you join his game, you connect to that server and you are the Client. The client in Blockland does not host the server, but joins a game.

Outside of Blockland, the Server is basically the computer hosting a database, game room, chat server such as Mumble or TeamSpeak, and can be used when multiple computers need to share information. The computers that access the database, join the game room, chat on the chat room, access files from the server are the Clients.

You may have to read this a few times to see what's going on, but if you understand, read on. Now that you know what a Client and a Server is, we can begin.
Let's put this into Blockland perspective. Everytime you chat in a server, CTRL + K, build, fire a weapon, etc. you are communicating with the server.

Communicating Client To Server

When you want to communicate with the server as a Client, you use this command in your script :
commandToServer();

Here's and example of it :

Code: [Select]
commandToServer('kill', %target);

"What is that?" you say? Let me break it down :
-commandToServer(); - This is a function (as you have learned earlier), that communicates with the server.
-'kill' - In these single quotes, I am saying that the command I want to perform is "kill".
-%target - You've learned already that this is a local variable, only usable by the function that it is in. You can think of it as I'm providing the server with extra details on my command. In this case, if I wanted my command to kill someone in the server, logically I would have to explain who should be killed, so I would want to add a variable such as %target in there.

So let's say I made this function :

Code: [Select]
function byebye(%target)
{
   commandToServer('kill', %target);
}

Now if I typed byebye("James"); in my script, it would tell the server to "kill" James.

That's basically how you communicate to the server as a client.

Receiving A Server Command
You know what? If a client uses commandToServer('kill', "fredrick55"); , then the server running default Blockland will probably not at all understand what to do. That's because you have to specify what the server has to do when someone tells it a command.

As the server-side, you must declare a function like this to handle things like that :
Code: [Select]
function serverCmdkill(%client, %target)
{
   findclientbyname(%target).player.kill();
}

In this example, findclientbyname(%target).player.kill(); is not terribly important for learning uses, but I'll break down the rest of it :

function / () / { } - You should be familiar with this, if not, read Functions above.

serverCmd - Alright, so server commands are a special type of function you can declare. If you want the server to respond to "/dig", you would use function serverCmdDig(). If you wanted the server to respond to "/buy", you would use function serverCmdBuy(). The simple idea is to keep "serverCmd" before the name of your command.

%client - Whenever you code what the server should do when it receives a certain command, you should always keep "%client" as the first argument after the first ( in the set of parentheses. The %client is a local variable you can use in the function which is basically the person who commanded the server to do something. %client is the client object but NOT the player.

%target - I skipped a comma, but whenever you have multiple arguments in a function, you insert a comma between them. Anyway, %target is an extra variable I'm using since logically I need to specify who should be killed.

When you type something like /kill Blake1, whatever spaces you type and whatever you type after a space is a new argument.

Using /kill Blake1 50 No (Let's just say the %target, %score [that i get], %displayKillMessage for example) I would be sending "kill" to the server with three arguments.

You now know how to make a client communicate with the server and specify how the server receives it.


Let's put your client / server command knowledge together so far :

Say this is my client side script :

Code: [Select]
function goodbye(%target)
{
   commandToServer('kill', %target);
}

Now say this is my server side script :

Code: [Select]
function serverCmdkill(%client, %target)
{
   if(%client.isAdmin) //By the way, these two slashes I put here are comments. Comments don't affect the script at all. This checks if the client is an admin.
   {
      findclientbyname(%target).player.kill();
   }
}

Now on the server, if I am an admin and there is a player on it called "BasonMason"..

Doing EITHER
Code: [Select]
commandToServer('kill', "BasonMason");

OR

Typing /kill BasonMason

Will do the same thing. That's right, typing a /slash command in your chat uses commandToServer(). They do the same thing.


Server to Client Commands
Alright, here I am, I'm the big old server and I want to tell the client to 'spinAround'.

So if client -> server is "commandToServer();", can you guess what server -> client is?

It's the function "commandToClient();", and it works in a similar way! Let's say I'm the server side in this script :
Code: [Select]
$Client = findclientbyname("Pacnet2013");
commandToClient($Client, 'spin');

The first argument you use in commandToClient is always the client object itself, most commonly named inside a function as "%client".
I then use the single quotes after that, simply to specify the command I want that client to perform.


Receiving a Command from the Server as a Client
Above, I used commandtoclient($client, 'spin', 1); as an example.
My client usually won't know what the heck the server wants it to do, so you also have to declare what happens in a client command declaration. It's very similar to serverCmd declarations.
This is my client side :

Code: [Select]
function clientCmdspin(%onOroff)
{
   turnleft(%onOroff); //Just a function that makes you turn around fast.
}

My argument is either 1 or 0 declared by the server, to spin or to stop spinning.


You should now know how to use client to server and server to client commands. They are a key part of Blockland. Good luck!



Pac mind if I quote you in the OP?

Pac mind if I quote you in the OP?

I don't mind, I was providing a contribution. Go ahead!

If (blah) Then is the most commonly used format in programming languages, so I refer to it as such.  Torque doesn't need "then" due to brackets
Most languages don't use "then"

Most languages don't use "then"
Most that I use however, do, so I refer to it as an if-then statement

I don't mind, I was providing a contribution. Go ahead!
When I update the thread I'll definitely add in your contribution, thanks!

I think the chatbot tutorial should be refreshed

Making Chatbots


You've probably seen somebody in a server automatically say hi when somebody joins, or somebody just says "get server ip" in the chat, and they automatically talk back with their sentence being the ip of the server. You've probably wondered what that is, and I will explain to you about these mods called Chatbots, and how to make them.

Chatbots are very simple to make, we will first make a chatbot that will make you say "Hey dude!" after you say "Hi Chatbot". The easiest to way to make this is by packaging.

Packaging

Packaging is a very useful thing in Blockland. With packaging, you can re-modify / add on to existing functions without having to re-write all the previous data again. Packages are very simple and creating one starts like this:

Code: [Select]
package PACKAGENAME
{
     //code stuff here
};

You now see that creating packages are similar to creating functions in Blockland. But there are a few differences. Packages do not need () to surround the name of the package (as far as I know), all you need to do is type package  and then a space with the name of your package after it. Also at the end of the package, is required: a semi-colon. Semi-colons are always needed to end packages. They are not used for functions, only packages and other things that other people might explain.

Modifying a function

The whole reason we want to create a package, is to modify the chat function so we can make ourselves say
"Hey Dude!" after we've said "Hi Chatbot". To do this, we just define the function we want to modify in the package. What we want to modify is clientCmdChatMessage.

That function is the function that is called after we've typed all of our stuff and press ENTER. The clientCmdChatMessage function has quite a few arguments, some of which even I am not familiar with, but all you need to be familiar with is 2 arguments. Here is the function labeled below:

Code: [Select]
function clientCmdChatMessage(%a, %b, %c, %fmsg, %cp, %name, %cs, %msg)
{
      //code here
}

What we need to memorize is %name and %msg. If you already know what a variable is, then it should be obvious to you. clientCmdChatMessage is called everytime someone chats. Each variable is always changed every time someone chats. %name is the name of the user who just sent a message, and %msg is the message that they typed. To implement the function into our package, refer to the code down here:

Code: [Select]
package Chatbot
{
    function clientCmdChatMessage(%a, %b, %c, %fmsg, %cp, %name, %cs, %msg)
    {
          //code here
    }
};

Parenting

Packages do not only exist for re-modifying functions. They also exist so that we can turn them on and off anytime we like. Packages are useful for torque programmers because whenever we wish to remodify a function, some might not use packages, and once they remodify that function, all the previous data is lost unless they enter it back in. If clientCmdChatMessage was modified without packages, then your chatting system would be broken and you would have to restart Blockland.

The code we have right now is in a package thankfully to me, and we are telling Blockland to remodify the function clientCmdChatMessage. But no, that is not all. We have not entered any code in there yet, so Blockland thinks we want clientCmdChatMessage to do practically nothing. So we have to type in a special little command that will enter all the previous data we've had. That command is called: Parent. And this is how we use it:

Code: [Select]
package Chatbot
{
    function clientCmdChatMessage(%a, %b, %c, %fmsg, %cp, %name, %cs, %msg)
    {
          parent::clientCmdChatMessage(%a, %b, %c, %fmsg, %cp, %name, %cs, %msg)
    }
};

Using that command will re-enter all the previous data that already existed in our function back in. Now we can apply any changes to this function after the Parent command.

If Statements

If statements exist to execute code when a certain thing happens. If statements are only executed once, but now that we can remodify the clientCmdChatMessage function, any if statement in there will be checked everytime somebody chats.

So guess what we will need to put in the if statement? Come on just guess and come back when you think you've got it.


Have you got it? If not then :[. The answer is we will need our if statement to check if our player is saying "Hi Chatbot". If you've got it then high-five. Unfortunately, we cannot just enter it in like that on our code, we need to enter it in by Torque's laws of syntax.

A way to use if statements to see if the player is saying "Hi Chatbot", is by this:

Code: [Select]
package Chatbot
{
    function clientCmdChatMessage(%a, %b, %c, %fmsg, %cp, %name, %cs, %msg)
    {
          parent::clientCmdChatMessage(%a, %b, %c, %fmsg, %cp, %name, %cs, %msg)
          if(%msg $= "Hey Chatbot!")
          {
                 //code here
          }
    }
};

Much is to be explained here. Every if statement needs an operator of some sort. the operator I used was $=. I will present a list of operators below, and what they do:

  • == if Value Variable is equal to
  • != if Value Variable is NOT equal to
  • $= if String Variable is equal to
  • && Used to connect 2 operators together. The if statement will run if both of them return true
  • || Used to connect 2 operators together. The if statement will run if 1 or the other returns true

There are probably more operators out there but i'm tired so I'll stop it here for tonight.

The reason I used $= in our code, is because %msg always returns a string, and $= is used for connecting strings. Only use == when you are connecting values.

So basically, when Blockland looks over the code, it sees our package, then makes our package, then it sees that we want to re-define the function clientCmdChatMessage, so it does that for us, and then it sees the parent command, so we just told it to write in all the previous data that was in it before we defined it, then it sees the if statement, and understands to execute any code when a message that any player sent is equal to "Hey Chatbot!".

Don't you feel pretty accomplished for getting this far? So do I. But there is 1 slight problem. If a message that ANY player sent is equal to "Hey Chatbot!". We probably don't want that, and we only want the if statement to run if WE said that line. So all we need to do is add in another operator in our if statement and add a little command:

Code: [Select]
package Chatbot
{
    function clientCmdChatMessage(%a, %b, %c, %fmsg, %cp, %name, %cs, %msg)
    {
          parent::clientCmdChatMessage(%a, %b, %c, %fmsg, %cp, %name, %cs, %msg)
          if(%msg $= "Hey Chatbot!" && %name $= $Pref::Player::Netname)
          {
                 //code here
          }
    }
};

As explained before, the && is used to connect 2 operators. So when the console looks at the if statement, it will check if the message that a player sent is equal to "Hey Chatbot", and it will check to see if the name of the player who sent that message is also equal to the name of $Pref::Player::Netname. $Pref::Player::Netname is the same as the username you set on Blockland when you first registered. Everytime you change your username, $Pref::Player::Netname is changed with it also.

Making our player talk

Yes, not much more to do now! All we need to do now is call a function to make a player talk! As you've (hopefully), read in Pacnet's tutorial, we need to send a message to the server to make us talk. Here is the command we need to send:

Code: [Select]
package Chatbot
{
    function clientCmdChatMessage(%a, %b, %c, %fmsg, %cp, %name, %cs, %msg)
    {
          parent::clientCmdChatMessage(%a, %b, %c, %fmsg, %cp, %name, %cs, %msg)
          if(%msg $= "Hey Chatbot!" && %name $= $Pref::Player::Netname)
          {
                 commandToServer('messageSent',"Hey dude!");
          }
    }
};

And yes, that is basically it. messageSent is a command we have to put in commandToServer to tell the server we want our player to talk. So basically, all you have to do is execute this little code through the means of a small script, or a plain add-on, and then, most importantly, you must type in the console:

Code: [Select]
activatePackage(packagename);
deactivatePackage(packagename);

ActivatePackage turns your mod on, like i've said before: Packages can be enabled or disabled. DeactivatePackage turns your mod off, so the command wont work anymore.


Up next: Advanced Chatbot Tutorial

commands still work even when you've disabled the package if i recall correctly (in some cases)

commands still work even when you've disabled the package if i recall correctly (in some cases)

Not if they were defined inside of the package that is being disabled.

Make sure to include:
packaging
default functions (just a list)
objects/classes
datablocks