diff --git a/docs/angelscript/game/meta.json b/docs/angelscript/game/meta.json index 45754fe1..ad750754 100644 --- a/docs/angelscript/game/meta.json +++ b/docs/angelscript/game/meta.json @@ -1,5 +1,5 @@ { "title": "Game", "type": "angelscript", - "weight": 0 + "weight": 1 } diff --git a/docs/angelscript/guide/chapter1.md b/docs/angelscript/guide/chapter1.md new file mode 100644 index 00000000..8d4d1480 --- /dev/null +++ b/docs/angelscript/guide/chapter1.md @@ -0,0 +1,110 @@ +--- +title: Chapter 1 - Introduction +weight: 0 +--- + +# Chapter 1 - Introduction + +## What will you learn in this chapter +In this chapter you will learn about: +- [AngelScript as a programming language](#angelscript), +- [Purpose of AngelScript in Strata Source](#what-can-you-do-with-angelscript), +- [Client - Server model of the engine](#client---server-model), +- [How to load code in the game](#loading-code), +- [Writing your own Hello World program](#your-first-script), +- [Testing out your own code](#how-to-test-out-your-code-in-a-basic-way) +- [Additional tips that might help you](#additional-tips). + +> [!TIP] +> In each chapter, you can easily navigate the page by clicking links in the "What will you learn in this chapter" section. + +> [!CAUTION] +> This guide assumes you have basic skills of programming in languages like Python, C/C++, Squirrel (VScript), etc. +> It is recommended you already have *some* experience in programming, although this guide aims to be as begineer's friendly as possible. +> Basic concepts will **not** be taught. + +> [!NOTE] +> It is recommended that while reading this guide, you will try out the things you have learned. This guide will include example tasks for you to do as a practice. + +--- + +## AngelScript +The [AngelScript's home page](https://www.angelcode.com/angelscript/) describes AngelScript as: +> The AngelCode Scripting Library, or AngelScript as it is also known, is an extremely flexible cross-platform scripting library designed to allow applications to extend their functionality through external scripts. + +Besides that, you can treat AngelScript as some sort of hybrid between C++ and Python. In some areas it behaves like C++, for example it is statically typed, meaning that when you are declaring a variable you also have to declare it's types, and it also implements it's own version of pointers (called handles); it also aims to help out users in writing code, whether by dissallowing certain operations or by assuming. More on that will be explained in later parts of the guide. + +Its use cases vary, it is much closer to pure engine code than VScript, meaning that you can for example program in custom entities, or custom commands. + +Its official documentation can be found here: [AS Official Docs](https://www.angelcode.com/angelscript/sdk/docs/manual/doc_script.html). + + +## What can you do with AngelScript +This question is not properly asked, because AngelScript will allow you to do mostly anything you want, however it's main task in Strata Source is to allow users to create custom entities, create custom commands, bind to in-game events, and more. + +While VScript (mainly) sits between entities and handles the interactions between them, AngelScripts sits in a level above, where AS can be treated as entities *themselves*. + +--- + +## AngelScript in Strata Source + +### Client - Server model +Before we get into writing your first script, there is one more thing you need to know. Most engines including Source in general, operate on the client-server model. Meaning that client code is separate from the server code, even on singleplayer. When you start a map in singleplayer you essentially create a one-player server that runs beside the client. This is very important because AS code can be loaded on both. Some functionality will only be available on the server (like entities) and some functionality will only be available on the client (like Panorama/UI). + + +### Loading code +Your first question might be: Where do I place the files containing my code? +The answer is pretty simple, each file that contains your code should be ended with the **.as** extension and be placed in the **code/** folder of a respective `Game` searchpath. Example locations would be `p2ce/custom/my-addon/code/` or just `p2ce/code/` (the latter not being recommended). + +You can name your files however you'd like. You can create custom directories, you can loosely place files, it all depends on what you're trying to achieve; in the long run it doesn't matter. What does matter are the "starting points" of sorts. The engine will not attempt to load any files besides 3 files placed **directly** in the **code/** folder: + +1. `init.as` - Will get loaded by server and client. +2. `sv_init.as` - Will only get loaded by the server. +3. `cl_init.as` - Will only get loaded by the client. + +### IDE and testing environment +It is suggested to use Visual Studio Code with the [AngelScript Language Server (sashi0034.angel-lsp)](https://marketplace.visualstudio.com/items?itemName=sashi0034.angel-lsp) extension. From there you can open the `code/` folder of your choice as a project and develop there. +The engine compiles scripts on every map load (you can use the `reload` command to recompile the scripts). + +### Your first script +Now, you should be ready to write your very first and own program that will print a Hello World message to the console. You might not know everything in the code below but don't get dissappointed! You should place this code into `cl_init.as` as it is a client command. + +```cpp +[ClientCommand("HelloWorld", "")] +void MyCommand(const CommandArgs@ args) { + Msg("Hello world from AngelScript!\n"); // You can place your own text here! +} +``` + +Now, the only thing left is to launch up the game, open the console and execute the *HelloWorld* command. + +> ### TASK 1: +> Run the HelloWorld program mentioned above. + +## How to test out your code in a basic way +For now you need to know how to run your code so that you will be able to solve tasks given to you with this guide. +In `sv_init.as` include: +```cpp +[ServerCommand("CodeTest", "")] +void CodeTest(const Command@ args) { + // Here you can put your code +} +``` + +The code in this function will run whenever you run the `CodeTest` command in game. Remember to `reload` to see the changes! +The `Msg(string)` function will serve you as a way to view your variables (like print or cout), just do `Msg(a)` where a is your variable and a will get printed to the console! +Remember to add `"\n"` to the input of Msg (or just call `Msg("\n");` after your message), otherwise everything will print in one line! + +> [!BUG] +> Some types such as `int` cannot be directly converted to string, and so you won't be able to put them directly into Msg(). +> > [!TIP] +> > In order to avoid that problem you can append to an empty string, just do `"" + a` and in most cases this will work: `Msg("" + a);` + +### Compilation errors +Most of times scripts will report errors before they are ran, on map load. This is why if you don't see your functionality (like when a command is not there in the console), scroll up and check the error. Additionally you can use the first tip in the [tip section](#additional-tips) and then use `reload`. + + +## Additional Tips + +> [!TIP] +> Reading console output can be tiresome as much more is happening in the console than just the script system. However, there is an easy way to just listen to the script system output. You can run `con_filter_text scriptsys; con_filter_enable 1` filter out anything that is not the script system. diff --git a/docs/angelscript/guide/chapter2.md b/docs/angelscript/guide/chapter2.md new file mode 100644 index 00000000..feafadcd --- /dev/null +++ b/docs/angelscript/guide/chapter2.md @@ -0,0 +1,116 @@ +--- +title: Chapter 2 - Value Types, Declaration & Assignment +weight: 1 +--- + +# Chapter 2 - Value Types, Declaration & Assignment + +## What will you learn in this chapter +In this chapter you will learn about: +- [Value Types](#value-types), +- [Declaration and assignment of value types](#value-types), +- [Auto keyword](#auto-keyword), +- [Constants and the const keyword](#constants), +- [Integer size reference table](#integer-size-reference-table). + +> Unfortunately, in this chapter you won't learn anything really interesting, but this knowledge is crucial to continue further. Data types in general are a very extensive subject, but you don't need to know everything. This chapter is supposed to teach you how to handle value types in your script. + +> [!NOTE] +> This chapter won't cover every detail about any of data types, it is recommended you visit the [Data Types Section](../game/type) of the wiki for more information. +> Alternatively, you can find references on the [AS Official Documentation](https://www.angelcode.com/angelscript/sdk/docs/manual/doc_datatypes.html), however please note that Strata's wiki will be the most representative, some functionality might have been changed! + +--- + +## Value Types +Value types are the more "primitive" types, and are only implemented in the backend by the Strata Team inside the engine itself. These types include: `int`, `string`, `bool`, `float`, `double`, etc. + +> [!WARNING] +> It is assumed you already know about these data types from other languages (mainly C++). This subsection will only provide information relevant to AngelScript itself. + +### Declaration and assignment +Value types can easily get assigned and can be passed by value to functions (more on that later). +To create a value type you usually perform a declaration and an assignment, or both at once: +```cpp +int myInt; // Declaration +myInt = 20; // Assignment + +string myString = "Hey!"; // Initialization +``` + +You can declare multiple variables of the same type at once: +```cpp +int myInt1, myInt2, myInt3; +``` + +Once declared, variables cannot change their type without redeclaration. This is not allowed: +```cpp +int myInt; +myInt = 3.2; // myInt is of type int, not float/double! +``` + +> ### TASK 1: +> 1. Create a program that will declare and assign variables of types `string`, `int`, `bool`, `double`, and then print them out to the console. +> 2. Do the same but use variable initialization. + +### Auto keyword +Although not recommended, the `auto` keyword will make the compiler automatically determine the data type of the variable: +```cpp +auto i = 1; // Will set type of i to integer +auto s = "My string"; // Will set type s to string +auto var = functionThatWillReturnAnObjectWithAVeryLongName(); + +// Handles (described in later chapters) can also be declared with auto +auto@ handle = @obj; +``` + +The `auto` keyword is not recommended for several cases. The main one of them is that you cannot immediately see the data type of a returned object especially from functions, like the one above. We don't know what that function will return. Another reason is that sometimes the compiler might guess wrong, especially in cases like integers, where you have multiple ways that `1` could have been described (e.g. int8/int16, both can describe `1`, even `bool` can). + +--- + +### Constants +Constant variables are variables that cannot change over the lifetime of the [variable scope](chapter3) they are created in. +You can define a constant variable using the `const` keyword: +```cpp +const int size = 31; +const auto st = "string"; // const also works with the auto keyword +``` + +Constants can be useful as a sort of configuration of the script itself. If you reuse a statically defined value you can instead define a global constant and then changing one value will change everything at once: +```cpp +const int MAX_SIZE = 16; + +string mystring = "lorem ipsum"; +my_func1(mystring, MAX_SIZE); // A function that does something with mystring, but also needs to have additional information +my_func2(mystring, MAX_SIZE) // Another function that does something else with mystring, but it also needs the same additional information +``` + +Constants are also a way to optimize your code. If you know that a variable won't change (or shouldn't change) after it's initialization, always make it a constant. +```cpp +bool function(string s, float i) { + const float value = s.length() - i; + return i > value; +} +``` + +> ### TASK 2: +> Write a program that initializes a constant variable with the `auto` keyword, and then tries to change it after. Observe the compilation error in the console. + +--- + +### Integer size reference table +The table below shows the minimum and maximum values for each integer subtype (don't worry about remembering this, just remember that it exists here): +|Type|Short description|Minimum Value|Maximum Value| +|---|---|---|---| +|int8| Signed, 8 bits |-128 | 127 | +|int16| Signed, 16 bits |-32,768 | 32,767 | +|int| Signed, 32 bits |-2,147,483,648 | 2,147,483,647 | +|int64| Signed, 64 bits |-9,223,372,036,854,775,808 | 9,223,372,036,854,775,807 | +|uint8| Unsigned, 8 bits, also represents characters (char) | 0 | 255 | +|uint16| Unsigned, 16 bits | 0 | 65,535 | +|uint| Unsigned, 32 bits | 0 | 4,294,967,295 | +|uint64| Unsigned, 64 bits | 0 | 18,446,744,073,709,551,615 | + +> [!TIP] +> The official AngelScript documentation mentions that the scripting engine has been mostly optimized for 32 bit datatypes (int/uint). Using these is recommended for the most part (unless you are dealing with numbers that don't fit into int/uint). + + diff --git a/docs/angelscript/guide/chapter3.md b/docs/angelscript/guide/chapter3.md new file mode 100644 index 00000000..9d8e12d0 --- /dev/null +++ b/docs/angelscript/guide/chapter3.md @@ -0,0 +1,163 @@ +--- +title: Chapter 3 - Statements, Expressions, Conditions & Variable Scope +weight: 2 +--- +# Chapter 3 - Statements, Expressions, Conditions & Variable Scope + + +## What will you learn in this chapter +In this chapter you will learn about: +- [Expression statements](#expression-statements), +- [Comparison operators](#comparison-operators), +- [Logic operators](#logic-operators), +- [If/else block](#ifelse-block), +- [Switch statement](#switch-statement), +- [Variable Scope](#variable-scope). + +> Statements, expressons, conditions and the variable scope are the foundation of every program or script. +--- + +## Basic statements + +Your code is like a recipe, and statements are the individual steps. + +Statements are a way to tell the script engine what it needs to do, we already used them in previous chapters, such as the assignment or declaration. + +### Expression statements +Any expression can be placed on a line as a statement. Examples of expressions include: +- Function call **()** operator - calls a function (more on functions later), +- Equals **=** operator - performs assignment, +- Add **+** operator - adds two values together, +- Substraction **-** operator - substracts two values from each other, +- Many more, such as **+=**, **-=**, **++**, etc. are available. More about them can be found in the [expression reference table](https://www.angelcode.com/angelscript/sdk/docs/manual/doc_expressions.html). + +Such statements need to end with the semicolon (`;`): +```cpp +b = a + b; +func(); +a += b; +``` + +AngelScript follows a specific instruction of operation order. Function calls are evaluated first bottom to top, then AS sticks to order of operations as specified in the [Operator Precedence](https://www.angelcode.com/angelscript/sdk/docs/manual/doc_operator_precedence.html) reference. + +You can force an order of operations by using parenthesis: +```cpp +float a = 1 + 1.0 / 2; // This will return 1,5 +float b = (1 + 1.0) / 2; // This will return 1 +``` + +> [!TIP] +> Order of how operators are evaluated for standard math operators such as **+**, **-**, **\***, **/**, etc. follow the standard Order of Operations. + +> ### TASK 1: +> Given `float a = 4; float b = 5;` Write a program that calculates the number c given by the equation: `c = (a - 2)^2 + (b + 1) / 2`. + + +### Comparison operators +Comparison operators are operators of which expressions evaluate to the `true` or `false` boolean values. An example of a comparsion operator is the equals (**==**) operator, which checks if the two values on boths sides of such operator are equal. Another type of a condition operator is the greater than operator (**>**), which checks if the value on the left side is greater than the value on the right side. For comparison operator reference please check the [expression reference table](https://www.angelcode.com/angelscript/sdk/docs/manual/doc_expressions.html). +```cpp +int a = 1; +int b = 2; +a == b; // Will return false, but it won't save the value anywhere, treat this as a whole: (a == b) + +b = 1; +bool result = a == b; // Result now stores the information if a and b were equal when it was defined. +``` + +### Logic operators +Logic operators are a way to combine comparison expressions in order to achieve one result: +- NOT - denoted as `!`, evaluates to true, if value is false and vice versa, +- AND - denoted as `&&`, evaluates to true, if both values are true, +- OR - denoted as `||`, evaluates to true, if even one of the values is true, else false if both are false, +- XOR - denoted as `^^`, evaluates to true, if and only if **one** of the values is true. + +```cpp +a && b; // AND +a && b || c; // A combination of AND and OR, a AND b is going to get evaluated first +a && (b || c); // You can use parenthesis to specify which operator should get evaluated first, here OR will get evaluated first +``` +> [!NOTE] +> Although AngelScript supports Python-like logic operator notation (and, or, ...) it is recommended to stick to the C-like notation. This is mainly because AS is much more similar to C in it's syntax, and also not every extension adding AS support for your IDE has support for the Python-like notation. + + +--- + +## Conditions +Conditions are a way to tell the engine to execute specific code only if a specific condition is met. For example, only add numbers if they are positive. +They should contain an expression that evalues to true or false, and they can be any sort of valid combination of comparison operators and logic operators, etc. + +### If/else block +The `if`/`else if`/`else` block is used to run specific code only on certain conditions. The `else if` and `else` are not required, but the block must start with an `if` statement. +```cpp +if ( a > 10 ) { // Condition 1 + // Run the code in here +} else if ( a < 10 ) { // Condition 2 + // If we haven't met condition 1, but have met condition 2, execute the code in here +} else if ( condition3 ) { + // We haven't met neither condition 1, nor condition 2, but we have met condition 3 +} else { + // If none of the conditions were met, execute this code +} +``` + +> ### TASK 2: +> Given two numerical values *a* and *b* (defined statically in your script) prints out an absolute value of their difference. + + +### Switch statement +The switch statement is a very useful tool for situations where you need to compare to a lot of different cases. It performs the *is equal* operation comparing a value to every value specified in case blocks. It is also much faster than a block of the `if`/`else if`/`else` statements. +```cpp +switch ( value ) { + case 0: + // Do if value == 0 + break; // Required keyword to go out of the switch block + + case 2: + case 3: + // Execute if value == 2 or value == 3 + break; + + default: + // Execute if neither cases were met +} +``` +> [!CAUTION] +> Each case requires a `break` statement after finishing code execution. This is because switch behaves more like the `goto` (C++) functionality, meaning that it doesn't stop executing code after finishing a specific case. The `break` statement will tell the code to go out of the `switch` block. This is also why in the upper example `case 2:` and `case 3:` can be used to both execute the same lines of code. + +> ### TASK 3: +> Given a string as a value (statically defined), write a program that would simulate a command-like behaviour using the switch statement. If the string is equal to: +> - "hello" - print "HelloWorld" to the console +> - "engine" - print "Strata Source" to the console +> - "name" - print "My name is Chell" to the console +> - on any other string - print "Command not recognized!" to the console + + +--- + +## Variable Scope + +Variable Scope determines which data can be accessed from where. In AngelScript the Variable Scope behaves exactly as the one in C++. +In general the Variable Scope makes programs use less memory by not holding expired (not useful anymore) information inside the memory, as an example: +```cpp +int number = 10; + +void my_func1() { + int my_number = 21; +} + +void my_func2() { + number = 20; // Success, number has been reassigned to 20 + my_number = 80; // Error, my_number has not been declared +} +``` +In this case my_number doesn't exist inside *my_func2*, it only exists inside *my_func1* and only for the duration of that function's execution. + +Statements such as `if`, `else`, `for`, `while`, `try`, etc. create local variable scopes each time, meaning that variables declared inside them cannot be accessed outside of them, contrary to how for example Python handles it (where scopes are only created inside functions). + +In AS, global variables are allowed, however: + +> [!NOTE] +> From the official documentation: *Variables of primitive types are initialized before variables of non-primitive types. This allows class constructors to access other global variables already with their correct initial value. The exception is if the other global variable also is of a non-primitive type, in which case there is no guarantee which variable is initialized first, which may lead to null-pointer exceptions being thrown during initialization.* + +> [!TIP] +> A good practice is to avoid global variables altogether, and use different means of sharing information between functions such as returning values or &out references (more on that in later chapters). \ No newline at end of file diff --git a/docs/angelscript/guide/chapter4.md b/docs/angelscript/guide/chapter4.md new file mode 100644 index 00000000..0e889f06 --- /dev/null +++ b/docs/angelscript/guide/chapter4.md @@ -0,0 +1,174 @@ +--- +title: Chapter 4 - Loops +weight: 3 +--- + +# Chapter 4 - Loops + + +## What will you learn in this chapter +In this chapter you will learn about: +- [While, do while loops](#while-do-while), +- [For loop](#for), +- [Foreach](#foreach), +- [Continue/Break keywords](#special-keywords). + +> Loops are a way to make the code repeat itself a certain amount of times, of which the amount of repetitions may vary depending on what is going on in the code. + +--- + +### Arrays - short introduction +> [!NOTE] +> This subsection is supposed to teach you the very basics of arrays, because next you will learn about loops, and loops are mostly useful for array manipulation. +> You won't learn in details what the array is and how to do operations on it, but you will learn how to create one and access its elements. + +An array is an ordered group of elements, of which there is a starting element and an element at the end. + +Code-wise it's a template object, as you need to specify of which data type its values will be. To create an array you can use the **{element, element2, ...}** assignment: +```cpp +array@ a = {0, 1, 2, 3, 4}; +array@ b = {true, false, false, true, false}; +array@ c = {.1, .3, .5}; +``` + +> [!NOTE] +> Since `array` and `dictionary` are reference types, you initialize them as an object handles (the @ symbol). For now, just remember that you add that symbol after the type name, it will get explained later on. + +To access elements in an array you use the index operator **[]**, where `[i]` will access the i'th element of the array (counting from 0): +```cpp +a[3] // = 3 +b[1] // = false +b[0] // = .1 +``` + +More on the arrays will be talked about in later parts of this guide. + +--- + +## While, do while +The `while (expression)` loop will execute code until the expression evaluates to false: +```cpp +int a = 10; +while (a > 0) { + a--; // Decrement (substract one from a) each time the code executes + // Code in here will stop executing when a will be equal to 0 +} + +other_code(); // This will execute after the loop +``` +The `while` loop will not execute the code (even once) if the condition evaluates to false from the very start. + +A `do while` loop however, will first execute the code inside the loop and only *then* check if the condition is true to execute it once more: +```cpp +int a = 10; +do { + a--; +} while (a > 0); // Note the semicolon +``` + +> [!WARNING] +> It is possible to create a never ending loop, the easiest way is to do `while (true)`. Such loops are most of times an error in programming. However, these loops can be an intentional decision when **you are sure the loop will at some time stop executing**, either with the `break` statement (more on that in a bit) or other ways. + +> ### TASK 1: +> Write a program that will print out "Hello again!" to the console 10 times. + +## For +A `for` loop is an advanced version of the `while` loop. It takes 3 arguments in its statement - `for (statement1; statement2; statement3) {...}`: +- Statement 1 - gets executed before the loop runs (but in the loop's variable scope), often used to intialiaze a local indexing variable, such as `int i = 0;`. +- Statement 2 - is a condition for the execution of the loop, checked before the loop executes the code inside. +- Statement 3 - is executed after a successful code execution inside the loop (every time). + +An example of a `for` loop can be a loop that cycles through every character in a string: +```cpp +array@ numbers = {1, 1, 2, 3, 5, 8, 13}; +for (int i = 0; i < numbers.length(); i++) { // For every i until i is greater or equal to the array length (this will ensure i won't go out of bounds) + numbers[i] // Represents the i'th number in the array + // After executing code do i++ (add one to i), so we can access the next element +} +``` + +> [!TIP] +> Statements 1 and 3 in for loops can be skipped, as an example `for (;condition;)` is a valid form of a `for` loop, and so is `for (int a = 0;condition;)` etc. + +> ### TASK 2: +> Given an array of integers, write a program that will add all of these integers and print out the result. +> > [!NOTE] +> > Because of the [Variable Scope](chapter3/#variable-scope), you will need to define a variable to store the sum outside of the loop. + + + + +## Foreach + +A `foreach` loop can be used to perform code for each item in a container objects. Container objects are objects that store values of other data types, such as the `array` object or the `dictionary` object. Its structure `foreach (vars : container_object)` consists of two parts: where vars contains declarations of the variable names, such as `int val`, and the container object is the, well, container object. Some objects unpack more than one variable, such as the `dictionary` objects that unpacks the key and the appropriate value. + +```cpp +array@ integers = {1, 2, 3, 4}; +foreach (int i : integers) { + // Code here, where i will cycle through every value in integers +} + +dictionary@ mydict = { + {"key1", value1}, + {"key2", value2}, + {"key3", value3} +}; +foreach (auto value, auto key : mydict) {// NOTE: the order is flipped here, as compared to e.g. foreach in Squirrel (VScript), value goes first + // Loop through mydict +} + +foreach (auto value : mydict) {...} // It is also possible to just loop over one of the elements to unpack +``` + +> ### TASK 3: +> Write a program that will print out every element of a given array. + + +## Special keywords + +These are the special keywords that can be used inside loops. + +### Break statement +The `break` statement is a way to exit a loop execution early. Calling it will cause the program to abort loop execution and continue executing code after the loop. + +```cpp +int a = 10; +while (a > 0) { + if (a == 5) { + break; + } +} +// This loop will stop executing when a will be equal to 5 +``` + +### Continue statement +The `continue` statement will cause the loop to stop and go to the next element. + +```cpp +int sum = 0; +for(int i = 0; i < 10; i++) { + + if (i == 4) { // If i is equal to 4, we are skipping it + continue; + } + + // This code will not execute for i = 4 + sum += i; +} +``` + +### Nested loops and special keywords +Keywords like `break` and `continue` work on the bottom-most loop in nested code, meaning that if you have code like this: +```cpp +while (condition) { + for (int a = 5; a < 10; a++) { + + if (a > 5) { + break; // This will break of the for loop, not the while loop! + } + } +} +``` + +> ### TASK 4: +> Create a **while (true)** loop that adds all integers until 20. diff --git a/docs/angelscript/guide/chapter5.md b/docs/angelscript/guide/chapter5.md new file mode 100644 index 00000000..1f334df4 --- /dev/null +++ b/docs/angelscript/guide/chapter5.md @@ -0,0 +1,348 @@ +--- +title: Chapter 5 - Functions +weight: 4 +--- + +# Chapter 5 - Functions + +## What will you learn in this chapter +In this chapter you will learn about: +- [Declaring functions and calling functions](#syntax), +- [Calling methods on built-in objects](#calling-methods-on-objects), +- [Default parameters](#default-parameters), +- [References and passing variables by reference to functions (`&in`/`&out`)](#references---short-intro), +- [Returning references and when it can be done](#returning-references), +- [Function overloads](#function-overloads). + +> Functions are a way to split up the code into re-usable parts. + +--- + +## Functions - Basics + +### Syntax + +As you already know or not, functions are a way of implementing routines that operate on an input and produce a result. In Layman's terms, you give it some data, it processes the data and (may, but doesn't need to) give you an output. + +A function declaration consists of 3 main parts: *return value*, *function name*, and the *parameters*. +These follow pretty much the same syntax as C++: + +```cpp +// return_value func_name(parameters), +// examples: + +int myCoolFunction() { // This function returns an integer + ... + return integer_variable; +} + +void myFunction() { + ... + // No return statement + + // or return statement without a value (useful if you want to return early) + return; +} + +bool myFunction(int a, int b) { + ... + return bool_variable; +} +``` + +Each function **must** have a return statement in each of its "paths". What that basically means, is that whatever you do in your function, it will always end with a return statement. The only exception is the `void` return type (which means return nothing), in which you can skip the `return` keyword entirely, or use the `return;` statement when you want to exit the function early. + + +### Calling functions + +Calling functions in code is very simple, you use the **function call `()`** operator, `func(arguments)`. In it, you include every needed argument: + +> [!NOTE] +> ""Variables"" in a function declaration are called **parameters**, while ""variables"" in a function call are called **arguments**. + +```cpp +int sum(int a, int b) { // a, b are parameters + return a + b; +} + +int just5() { + return 5; +} + +int a = sum(1, 2); // 1, 2 are arguments + +a = sum(a, just5()); // just5 will get evaluated first, then its result will get passed to sum +// a = 5 +``` + +Calling a function is a statement, which means it can be freely used in expressions in every combination. You can treat `func(p)` as a value that you do operations with. + +### Calling methods on objects +Some objects such as `string` or `array` implement methods. For now, you can think of methods as functions that sit inside the object (variable), and operate on that object. You can invoke them by using the `.` operator and then the function call. +```cpp +string mystr = "ABC"; + +mystr.length(); // Returns the length of this string (3) +``` + +For a list of available methods per each type please refer to the [types section](../game/type) of this wiki. +> [!NOTE] +> Primitive types (`int`, `float`, `bool`, etc.) don't implement any methods. + +### Recursiveness + +Like in any other language, a function can call itself. This is function is then called a *recursive* function. + +--- + +## Parameters + +Function parameters in AngelScript can be a bit confusing, since AS has custom keywords and custom behaviors for different types of parameters. + +### Default parameters +Sometimes you want to add additional functionality to your function, but for most cases you already know what it should do, although you still want to include a customizable option for fine-tuning. You can do that by default parameters. + +Each parameter can have a default value assigned to it, like so: +```cpp +void myFunc(int a = 5, int b = 1) {...} +``` + +This function can be called with *0*, *1*, and *2* arguments, and each call will be valid. +Calling it with 0 arguments will mean that `a` will be set to `5`, and `b` to `1`. Calling it with one argument will set a to that arguments value and so on. +```cpp +myFunc(); // a = 5, b = 1 +myFunc(2); // a = 2, b = 1 +myFunc(2, 5); // a = 2, b = 5 +``` + +> [!NOTE] +> It is currently not possible to explicitly set each parameter to a specific argument. In Python for example, doing `myFunc(b=2)` is allowed and will set `b` equal to `2`, however this is not the case in AngelScript. +> > [!TIP] +> > You can use [function overloads](#function-overloads) to overcome this issue. + +### Constant parameters + +Constant parameters work just like constant variables. If declare a certain parameter constant, you won't be able to change it in any way. +```cpp +void myFunc(const int a, const bool y = true) // Default parameters can also be constants +``` + +One important note is that declaring a const parameter will make the compiler not copy the object (if it ensures the object's lifetime). More on that will be in the next chapters. + +> ### TASK 1: +> Create a function that computes the nth number of the fibonnaci sequence. It should take uint as the parameter (n) and return an uint (the number). You can tackle this problem recursively (using recursion) or iteratively (using a loop). It is recommend to try out both. + +### References - short intro +Before we delve into the next subchapter, you need to know what *references* are. In each computer, variables are stored in memory. You can visualize computers memory as a some sort of a box with labels. Each label has some space that it describes, and there can be an item in each label. Such items are our variables, and these labels are memory addresses. In such way, the computer knows where to look for these variables when it needs to find them. + +References are just the labels we have been comparing to, they *are* the address of the variable they correspond to. + +They are denoted with the **&** symbol. Conceptually: +```cpp +string mystring = "lorem ipsum"; +&mystring // Memory address of mystring +``` + +In angelscript you cannot directly manipulate references, but you can do many useful things when you combine functions and references. The AngelScript compiler will automatically manage referencing (getting a variables adress) and dereferencing (looking up a variable from an adress). + +### Reference parameters +Functions can be set to use references as parameters. + +In the examples shown above every argument was **copied**. Here's a better example: +```cpp +void func(int c) {...} + +int a = 1; +func(a); +``` +In this example, before `c` gets assigned a value from `a`, the value of `a` gets copied first, and only after that the assignment occurs. This happens, so that doing any operations on `c` in `func` will not cause `a` outside the function to change in any way. + +However, passing by reference changes that mechanism. Since now, the thing that gets copied is the memory address, not the actual variable value. Meaning that if we were to pass by reference in `func` above, doing any operation such as `c = 5;` would cause `a` to change accordingly (a = 5). + +Telling the compiler that you want to pass by reference gets done in the function parameters declaration, like so: +```cpp +void func(int& c) // This is a pass by reference +``` + +No special syntax for calling is needed: +```cpp +int a = 1; +func(a); // a gets passed by reference +``` + +AngelScript implements more functionality to passing by reference, and that includes 2 options: + +#### &in +This marks the parameter as an input to the function. This option provides little to no benefit as to just passing by value (copying), as the compiler still has to ensure the object won't get modified outside the function, and the only way to do that is to make a copy. + +> [!TIP] +> Combining `&in` with `const` can however, yield a way more optimized code. `&in` should almost always be used whenever you are using a `const` parameter. + + + +#### &out +This option specifies that this parameter is an output of a function. This is especially useful whenever you have functions that need to have multiple output values. At the start of a function's execution, this reference will point to an uninitialized variable. After the function returns, the value assigned to this variable will be copied over to the appropriate argument. + +Example usage of passing by reference of all 3 options: +```cpp +// Example of &in usage +void PrintMessage(const string&in msg) { // This will make the compiler try to not copy the argument when calling the function, as we are not modifying it in any way. + Msg(msg + "\n"); // Convenience function that prints the message with \n appended +} + +// Example usage of &out +bool WholeDivision(int a, int b, int&out result, int&out rest) { + // Calculates the whole part of a/b and the rest + // Returns true if the operation can be done. + if (b == 0) { + return false; // We cannot divide by zero + } + + result = a / b; + rest = a % b; + + return true; +} + + +int myresult, myrest; +WholeDivision(10, 3, myresult, myrest); //This will set myresult and myrest to the appropriate (3 and 1 respecitvely). +``` + +> [!NOTE] +> AngelScript also supports a 3rd mode, `&inout` or `&`, but this is only allowed for reference types (more on that later), and additionally, Strata Source is configured to only pass reference types by reference (pass by value is disabled), which means that there is no need to specify pass by reference for these types anyway. + + +--- + +## Returning references + +Functions can also *return* references. Meaning that they return an address to an object, rather than the object itself. In previous examples we have discussed functions that return by value, meaning that the value of the variable that gets returned, gets copied to a temporary location and then gets "transfered" over to the variable outside the function: +```cpp +int func(int a) { + return a * 2; +} + +int b; +b = func(2); // Result of func(2) gets stored in a temporary location and then copied over to b. + +func(2) = 1; // This will not work. +``` + +Returning references works in a different way, we return an address, that means the actual value of the variable never gets copied which saves on performance. Additionally, it allows you to do operations on the return value of a function. To declare a function that returns a reference, you append the `&` symbol at the end of the type name in the return type. + +Before we overview examples, there is one more thing to discuss about returning references. Not every variable can get it's reference returned. In general, variables that don't exist outside the function will not be able to get returned by reference, because they will get erased once the code gets out of the function. + +#### 1. References to global variables are allowed. +Returning references to global variables is allowed, because the variable won't get destroyed outside the function. Example: +```cpp +int a = 1; + +int& addToA(int b) { + a + b; + return a; // Like in reference parameters, no additional syntax is needed. +} + +//This will allow us to do something like: +addToA(1) = 3; // We add 1 to a, but then we change a to be equal to 3. +``` + +#### 2. References to class members and `this` are allowed. +> [!NOTE] +> This information will be useful once we get to custom classes and reference types, so if you don't know what these are you can skip this for now. + +References to class members (properties) and to ourselves (`this`) are allowed to be returned by methods. + +```cpp +class myclass { + int myvar; + + int& GetMyVarRef() { + return this.myvar; + } + + myclass& GetMe() { // Note: this will automatically translate to myclass@& (reference to the handle of myclass) + return this; + } +} +``` + +#### 3. Returning a reference to a local variable is not allowed. +Returning a reference to a local variable is not allowed, this is because the variable will not exist after the function returns. +```cpp +int& myFunc() { + int a = 1; + return a; // a will not exist outside of myFunc, this is not allowed +} +``` + +#### 4. Returning a reference to a deferred parameter is not allowed. +Values passed by reference into a function cannot be returned by reference. This is because AS does additional cleanup after the function returns, hence why there is no guarantee that an object passed by `&in`/`&out` will exist after the function returns. + +```cpp +int& func(int a&in ) { + return a; // This is not allowed +} +``` + +> ### TASK 2: +> Create a function that splits a string into two same-length parts. It should take a string and return a boolean if the string can be split (if the strings length is not divisible by two you cannot create two equal-length parts), and it should also return these two parts (use `&out`). + +--- + +## Function overloads +Function overloading is a very powerful concept, as it allows you to declare a function multiple times, each time with a different set of parameters. The compiler will then attempt to choose the best "fit" for which exact function to call (the criteria of how it does so are available on the [official documentation](https://www.angelcode.com/angelscript/sdk/docs/manual/doc_script_func_overload.html)). + +This is mainly used for functions that can accept multiple combinations and types of parameters, but produce a similar result. +```cpp +void myFunc(int a) {...} +void myFunc(string a) {...} + +myFunc(10); // Will call the first option +myFunc("a"); // Will call the second option +myFunc(10.5); // Will call the first option (but float will get converted to int) +myFunc(false); // Will cause an error since none of the options specify bool as a parameter +``` + +Default parameters are also allowed to be used in overloading, but you have to be careful whilst doing so. If you define your function wrong, the compiler will not be able to decide whether it should use an overload or use a default parameter. + +```cpp +void myFunc(int a, int b = 2) {...} +void myFunc(int a) {...} + +myFunc(1, 3); // Will work, since there is only one option. +myFunc(1); // Will not work, since the compiler doesn't know which option to choose (should it use the first and set the default parameter or should it use the second?) + +void myFunc(string a) {...} +void myFunc(int a, string c = "C") {...} // Same goes for different types of default parameters + +myFunc("A"); // Will work, there is only one option +myFunc(1); // Now there are 3 options to choose from and none are more important +myFunc(1, "A"); // Will work +``` + +> [!WARNING] +> Different return types are allowed for overloads, e.g. one function can return an int, whilst other can return a string (the auto keyword is useful here); however the compiler will not take the return type as a criteria for deciding which overload to use. + +> ### TASK 3: +> In the default parameters section there was a problem mentioned about how you cannot explicitly set custom parameters. Given a function: +> ```cpp +> int printXTimes(string msg, string end = "\n", int x = 1) { +> for (int i = 0; i < x; i++) { +> Msg(msg + end); +> } +> } +> ``` +> Find a way to use it to print 10 times the message "CONSOLE SPAM!" **without specifying a value for the `end` parameter!** +> > [!TIP] +> > You can call an overload to a different function in an overloaded function: +> > ```cpp +> > void myFunc(int a) {...} +> > +> > void myFunc(int a, int b) { +> > myFunc(a); +> > } +> > ``` + +> [!NOTE] +> If you completed the task above, congratulations! This was one of the harder tasks. However, please note that this way of solving that problem is only viable when your default parameters have different types, because if they don't, the overload will not work. \ No newline at end of file diff --git a/docs/angelscript/guide/chapterX-1.md b/docs/angelscript/guide/chapterX-1.md new file mode 100644 index 00000000..dbb1cd7c --- /dev/null +++ b/docs/angelscript/guide/chapterX-1.md @@ -0,0 +1,27 @@ +--- +title: Chapter X - Reference Types +weight: 4 +--- + + +# Chapter X - Reference types + +### Declaring template objects +Sometimes objects are described with a template, such as the `array` object. Because the `array` class is supposed to be versatile, it can support different types of data for it's values; you can have an array of integers, an array of floats, an array of strings, etc. There is no need to re-create the array class for each and every available data type, as this is where the template functionality is used for. + +When declaring an array you need to specify the data type of its values, like so: +```cpp +array string_array = {"string1", "string2", "string3"}; // Create an array of strings +array myArray = {1, 2, 3, 4}; // Create an array of integers +``` + +Functions can be templates too, an example of such function can be the cast function, which converts one data type to another (if possible) (more on the cast function later): +```cpp +obj1 myobj1; +obj2 myobj2; +@myobj1 = cast(@myobj2); // Cast function will convert obj2 into obj1 +``` + +> [!NOTE] +> It is currently not possible to create your own custom template objects, although this functionality is planned for future releases of AngelScript. + diff --git a/docs/angelscript/guide/chapterX.md b/docs/angelscript/guide/chapterX.md new file mode 100644 index 00000000..97041445 --- /dev/null +++ b/docs/angelscript/guide/chapterX.md @@ -0,0 +1,90 @@ +--- +title: Chapter X - Object Handles +weight: 5 +--- + +# Chapter X - Object Handles + +## What will you learn in this chapter +In this chapter you will learn: +- What are Value Types, +- What are References and how to use them, +- What are Reference Types. + + +Unfortunately, in this chapter you won't learn anything really interesting, but this knowledge is crucial to continue further. Data types in general are a very extensive subject, but you don't need to know everything. This chapter is supposed to teach you how to handle data in your script. Described below are various "types" of data types, and their differences. + +--- + +## Object handles + +Object handles are like smart pointers from C++, they don't actually hold data themselves, rather they hold an address in memory (reference) that can be used to locate the object they point to. + +### Declaration +An object handle is declared by appending the **@** sign after the data type name, e.g.: +```cpp +object@ handle; +``` +This code will create a handle of type `object` and point it to null (meaning that it doesn't actually point anywhere). + +> [!CAUTION] +> It is not guaranteed that handles will actually point to valid data. Handles initialized like the one above point nowhere, and trying to perform any operation on them (such as calling methods) will cause an exception. + +> [!NOTE] +> None of the Value Types (primitives) have object handles. + +You can access the handle of any reference type by prepending the **@** symbol to the variable: +```cpp +object my_object; +@my_object; // This is a handle to my_object +``` + +### Expressions +In expressions, object handles are treated exactly the same as object variables themselves. For reference types they are essentially the same. Meaning that: +```cpp +object my_object; +object@ my_handle = @my_object; +my_handle is my_object // Is true + +//Calling methods can be done like so (both ways are correct) +my_handle.Method(); +my_object.Method(); +``` +In most of times the compiler will automatically know what you are trying to do, in order to explicitly call a handle operation you have to **prepend the variable name with the handle symbol (@)**. + +```cpp +object obj1; +object@ objhandle; + +objhandle = @obj1; // This will not work, and will make the script not compile. +@objhandle = @obj1; // This is a proper handle assignment, @objhandle gets set to point to obj1. +@objhandle = obj1; // This will also work because of object variables being handles internally, but is confusing to read, and so - not recommended. +``` + +--- + +The below section of the Object Handles subchapter contains more detailed information about the implementation of handles in AngelScript. If you don't feel like delving deeper into this subject you can skip the rest of this section for now, remember that you may always return here after you feel accustomed to object handles. + +As an example, let's assume the `object` class implements opAssign, trying to do: +```cpp +my_object = 10; +``` + +Will result in an error, because you are not allowed to do value assignment on a reference type. However, you will be able to do: + +```cpp +@my_object = 10; +``` + +Because that calls the internal opAssign method (which should return a reference to the `object` (us)), and so we are actually doing a handle assignment (that assigns the handle to the same object, but in which opAssign has modified the internal properties). + +You can also initialize objects this way: +```cpp +object@ my_object = 10; +``` +This is a completely valid way of declaring and initializing a variable. This code will call the default constructor, then opAssign(10). + +--- + +## Reference types + diff --git a/docs/angelscript/guide/meta.json b/docs/angelscript/guide/meta.json new file mode 100644 index 00000000..76da0b32 --- /dev/null +++ b/docs/angelscript/guide/meta.json @@ -0,0 +1,4 @@ +{ + "title": "Begineer's Guide", + "weight": 0 +}