Register FAQ Search Today's Posts Mark Forums Read
Go Back   JazzJackrabbit Community Forums » Open Forums » JCS & Scripting

Complementary scripting tutorials

Seren Seren's Avatar

JCF Member

Joined: Feb 2010

Posts: 864

Seren is a name known to allSeren is a name known to allSeren is a name known to allSeren is a name known to allSeren is a name known to allSeren is a name known to all

Jan 14, 2016, 12:51 PM
Seren is offline
Reply With Quote
Complementary scripting tutorials

I get the vibe that many JJ2+ script writers learned AngelScript by reading others' scripts, experimenting with their own, and referring to the scripting API when necessary. Learning through practice is a good, easy method, but it leaves many educational lacks that may slow down your coding, limit your possibilities, decrease your code's clarity, or make it difficult to expand. In this thread I intend to post short, bite-sized tutorials, each aimed to extend your knowledge about a certain scripting topic. The tutorials are generally meant be independent from each other so you can start reading from any of them you want, and if they require prior knowledge of other subjects I'll make that clear at the beginning of the tutorial in question. Notice however that these tutorials are certainly not aimed to be read by complete beginners: you are expected to possess basic scripting skills that just need some expansion and polishing. If you had never written a script of your own, you will probably not benefit from reading these. Finally, I encourage you to leave feedback, either by posting in this thread or by any other means you can reach me. Feel free to suggest topics you'd like me to cover or just say you found a post useful. If I don't feel like anybody benefits from this thread, I won't bother to continue posting in it.

Tutorials available so far:
Strings
Enums
__________________

I am an official JJ2+ programmer and this has been an official JJ2+ statement.

Last edited by Sir Ementaler; Feb 9, 2016 at 06:05 AM.
Seren Seren's Avatar

JCF Member

Joined: Feb 2010

Posts: 864

Seren is a name known to allSeren is a name known to allSeren is a name known to allSeren is a name known to allSeren is a name known to allSeren is a name known to all

Jan 14, 2016, 12:52 PM
Seren is offline
Reply With Quote
Strings

Escape sequences

You probably not only encountered, but also already used strings in your own scripts. They're a basic built-in object class designed for storing text. String literals1 begin and end with either single quotation marks (') or double quotation marks ("). No surprise so far. However, did you ever consider what you'd have to do if you wanted to use a string that contained both of those characters inside it? If the text is surrounded by double quotation marks, you can't simply place another double quotation mark inside it, because the compiler would treat it as the end of the string and the intended result wouldn't be achieved. Instead, you should make use of what's called "escape sequences".

Escape sequences are character sequences of special meaning that the compiler replaces with a specified character. In AngelScript, escape sequences are created by typing backslash (\) followed by a certain character or characters. The sequence \" will be replaced by a double quotation mark and the sequence \' will be replaced by a single quotation mark, but that's not all escape sequences there are: \t is replaced by a single tab character, \n is replaced by a new line feed character, which you may find useful for drawing multi-line text on screen, \r becomes a carriage return character, which you probably won't ever need unless you decide to work with text files, and \0 is a null character (not to be mistaken with the numerical character '0'; null is a type of a control character2). Granted, these aren't something you use commonly in AngelScript, but it's worth knowing they exist.

Now if you've been reading carefully, you should be wondering how you include the backslash character in a string if the compiler expects it to start an escape sequence, and the answer is more escape sequences: \\ is an escape sequence that produces a single backslash. This is very important to know if you happen to write a string that's meant to remind a Windows file path. Consider a naively written string "C:\Games\". When the compiler reaches it, it will see a double quotation mark and realize it's dealing with a string. It will parse the first two characters and then reach \G. That's not an escape sequence it knows, so it will ignore that bit and throw a warning that will be displayed by the chatlogger. Then it reads further and finds \". It understands it as an instruction to insert a double quotation mark into the string, and then continues parsing all following code as a string. Eventually it reaches the end of the script file, and because the string should have been closed but wasn't, it submits an error to the chatlogger. Thus, backslashes in strings must always be escaped and the valid form of that string would've been "C:\\Games\\".

Finally, there are some universal escape sequences that allow you to insert any ASCII or Unicode character into a string as long as you know its hexadecimal code point. Or well, not really, since JJ2+ doesn't actually support Unicode strings, but the sequences can still come in useful. Those are \xFFFF, \uFFFF, and \UFFFFFFFF, where F's should be replaced by hexadecimal (base 16) digits. The number of digits must exactly match the number of F's given here, except for \x, which accepts anywhere between 1 and 4 digits. One case when this is particularly worth remembering is when you need to insert a section sign character (§) to modify spacing between letters. Simply type \xA7 or \u00A7 and it's there.

Heredoc strings

Escape sequences can be useful, but there are times when they simply make your string look really terrible. Or on other occasions you have a really big chunk of multi-line text and it would be inconvenient to replace characters with their corresponding escape sequences. AngelScript offers a solution to that, named heredoc strings. Heredoc strings are placed between two sets of triple double quotation marks (""") and can safely contain backslashes, quotation marks, and new line characters. What should you do if you want your heredoc string to also contain triple double quotation marks? AngelScript doesn't tell, which is most unfortunate because most programming languages that have heredoc strings offer solutions to this kind of problems, but luckily the necessity to ever do that is unlikely enough to happen to you.

Methods and supporting functions

Strings come with some functions and methods that are listed but not explained on the AngelScript website, and not mentioned at all within the JJ2+ scripting API, but definitely worth knowing as they can save a lot of time. Here they are:

Methods:
  • uint length() const - Returns the number of characters in the string.
  • void resize(uint n) - Sets the number of characters in the string to n. If n is less than the current size, the string is reduced to its first n characters. If n is more than the current size, an appropriate number of null characters (\0) is appended at the end of the string.
  • bool isEmpty() const - Returns whether the string is empty, i.e. whether the number of characters is zero.
  • string substr(uint start = 0, int count = -1) const - Returns a substring of the string, starting at the character with index start and containing count characters, or if count equals -1, containing the remainder of the string.
  • int findFirst(const string &in str, uint start = 0) const - Finds the first occurrence of substring str within the string, starting the search from start. Returns index of the first character of the found substring or -1 if the substring is not found.
  • int findLast(const string &in str, int start = -1) const - Finds the last occurrence of substring str within the string, starting the search from start, or if start equals -1, from the end of the string. Returns index of the first character of the found substring or -1 if the substring is not found.
  • array<string>@ split(const string &in delimiter) const - Separates the string into substrings wherever the character sequence delimiter is found and returns the resulting array. The substrings don't contain the delimiter. This can be very useful for creating custom commands, as splitting user input by spaces (as in, text.split(" ")) greatly simplifies parsing. For example, if text is "!ban 5 60m", the resulting array will be {"!ban", "5", "60m"}, which is much easier to implement logic for. This method can also be used to divide the content of a loaded text file into separate lines, using text.split("\r\n") for Windows files or text.split("\n") for Unix files3.

Functions:
  • string join(const array<string> &in arr, const string &in delimiter) - Joins the array of strings arr into a single string, inserting delimiter between substrings. This essentially reverts the operation of split. Like split, it can come in useful during command parsing, mainly if the final argument of a command is allowed to contain multiple words, for example after text "!ban 5 60m airboard bug abuse" is split, the resulting array is {"!ban", "5", "60m", "airboard", "bug", "abuse"}. After processing the first 3 arguments of the command we can remove them from the array and end up with {"airboard", "bug", "abuse"}, which we can then join with spaces to obtain "airboard bug abuse".
  • int64 parseInt(const string &in str, uint base = 10, uint &out byteCount = 0) - Returns an integer represented by the string str. For example for the input string "1056", the function will return 1056. The base argument determines the numerical base used for parsing, which must be either 10 or 16, otherwise the function fails. If the function encounters a character that is not a valid digit in the provided base or a '+' or '-' sign after the first position, it stops parsing and returns the integer calculated up to that point. byteCount may be used to obtain the number of valid characters parsed.
  • double parseFloat(const string &in str, uint &out byteCount = 0) - Returns a floating-point number represented by the string str. For example for the input string "0.635", the function will return 0.635. If the function encounters a character that shouldn't occur in a valid representation of a floating-point number, it stops parsing and returns the value calculated up to that point. byteCount may be used to obtain the number of valid characters parsed.
  • string formatInt(int64 val, const string &in options = "", uint width = 0) - Returns a text representation of the provided integer val. Available options explained below. The width argument specifies the minimum length (in characters) of the result. If the result is shorter than the minimum length, an appropriate number of spaces will be appended on its left (or right if left justified; see options below).
  • string formatFloat(double val, const string &in options = "", uint width = 0, uint precision = 0) - Returns a text representation of the provided floating-point number val. Available options explained below. The width argument specifies the minimum length (in characters) of the result. If the result is shorter than the minimum length, an appropriate number of spaces will be appended on its left (or right if left justified; see options below). precision specifies the minimum number of digits to appear after the decimal point character.

In formatInt and formatFloat, options should be a string that's a combination of the following characters:
  • 'l' (lowercase L) - Left justify. If length of the result is less than width, space characters will be used to justify the result to left rather than the default of right.
  • '0' (zero) - Pad with zeroes. If length of the result is less than width, an appropriate number of zeroes will be appended in front of the result.
  • '+' (plus) - Always include the sign, even if positive. If the number is positive, a plus sign will be appended in front of the result.
  • ' ' (space) - Add a space in case of positive number. If the number is positive, a single space will be appended in front of the result.
  • 'h' - Hexadecimal integer small letters. The integer is formatted in base 16 and lowercase letters a-f are used as digits. Not available in formatFloat.
  • 'H' - Hexadecimal integer capital letters. The integer is formatted in base 16 and uppercase letters A-F are used as digits. Not available in formatFloat.
  • 'e' - Exponent character with small e. Scientific notation is used and signified by a lowercase e. Only available in formatFloat.
  • 'E' - Exponent character with capital E. Scientific notation is used and signified by an uppercase E. Only available in formatFloat.

A recent update of AngelScript also added formatUInt, analogous to formatInt but operating on unsigned integers, however this function is not available in JJ2+ yet (and only comes in useful if you work with really big numbers, we're speaking 18-19 digits).

Operators

Finally, strings support a number of operators, some obvious and some less. It's very useful to know them as it can save you a lot of redundant code. Naturally, strings can be assigned (=) and tested for equality (== and !=). It's less common knowledge that they can also be compared using other relational operators (<, >, <=, >=). Such comparison is performed according to character codes, i.e. for most common uses, ASCII. It's useful to notice, for example, that if both compared strings are lowercase English words, the one that will be considered "smaller" is the one that precedes the other alphabetically. This has the advantage of allowing to quickly sort an array of words according to alphabet with use of the array method sortAsc (which may be discussed in another tutorial).

However, in ASCII, uppercase letters will always be considered "less than" lowercase ones (take a look at an ASCII table). This is quite unfortunate for the purpose of sorting alphabetically in case our words happen to contain mixed lowercase and uppercase characters. Luckily, ASCII is actually a fairly well designed system, in which the difference between an uppercase letter and its lowercase equivalent is always exactly 32. This is essential information, because it means that we can switch the case of a letter as long as we know its character code.

Most programming languages provide a way to convert between charcters and character codes. AngelScript does too, but it makes it particularly bothersome and doesn't really document it. You do it using the index operator ([]). For example, by typing text[0], we obtain the character code of the first character of text. Like most functionalities, it's available even for string literals, so "A"[0] is a valid expression that has the value of the character code of the letter A (65). That means you don't have to look up the ASCII code of a specific character when you need it in your script (useful in connection with jjKey, as keyboard codes of digits 0-9 and letters A-Z are the same as their ASCII codes, and jjKey["A"[0]], even if not pretty, will be easier to understand than jjKey[65]).

The index operator can be used not only to read, but also to set a character code at the selected position, e.g. text[0] = "!"[0]; will set the first character of text to an exclamation mark. In either case, like when working with arrays, keep in mind that the index has to be valid, i.e. non-negative and less than the string length, otherwise a run-time "index out of bounds" error will occur.

With this information, you should be able to understand the following function that converts a string to lowercase:
Code:
string lowercase(string text) {
  for (uint i = 0; i < text.length(); i++) {    // for each character
    if (text[i] >= "A"[0] && text[i] <= "Z"[0]) // if the character is an uppercase letter
      text[i] += 32;                            // convert it to its lowercase equivalent
  }
  return text;
}
It's not the most efficient way to do it, but it works.

The last pair of operators supported by strings are concatenation operators + and +=, which you probably already encountered. Although they are represented by the same characters as arithmetic addition operators (such as in the expression 1 + 1), they serve a completely different purpose and have different properties. Concatenation joins two strings together, simply appending one at the end of the other. As obvious as it may sound, you should notice that in contrast to arithmetic summation, the order of operands in concatenation does matter: "A" + "B" is not the same as "B" + "A"; one equals "AB" and the other "BA".

AngelScript simplifies syntax by allowing one of the operands of the concatenation operator to not be a string but another data type, such as a Boolean, integer, or float. Booleans will be appropriately converted to strings that say either "true" or "false", while integers and floats will be formatted with use of respectively formatInt and formatFloat implicitly called with default parameters. This can shorten your code, but remember to get the order of operations right: the expression "two: " + 1 + 1 will result in a string saying "two: 11" and to achieve "two: 2" instead, you should write "two: " + (1 + 1). The expression "zero: " + 1 - 1 won't compile at all, because the concatenation will occur first, and an attempt to compile the operation "zero: 1" - 1 will cause an error as the minus sign doesn't have a meaning in strings.

Summary

Hopefully that's all you could ever want to know about strings. To sum it up, strings are a data type for storing text, string literals can contain escape sequences for representing characters you can't otherwise include in them, and a special syntax called heredoc strings exists for when you don't want escape sequences to be interpreted or want to include long multi-line text. Strings have many useful methods and supporting functions, among them ways to obtain and modify length, search for desired terms, split into an array and join it back into a string, and convert between strings and arithmetic data types. They also support several operators, in particular ones that allow lexicographical comparison according to their internal ASCII code representation, obtaining and modifying character codes at selected position, and concatenation.

Useful links:
AngelScript documentation of strings
ASCII chart
__________________

I am an official JJ2+ programmer and this has been an official JJ2+ statement.

Last edited by Sir Ementaler; Jan 16, 2016 at 08:28 AM.
Stijn Stijn's Avatar

Administrator

Joined: Mar 2001

Posts: 6,964

Stijn is a splendid one to beholdStijn is a splendid one to beholdStijn is a splendid one to beholdStijn is a splendid one to beholdStijn is a splendid one to beholdStijn is a splendid one to beholdStijn is a splendid one to behold

Jan 14, 2016, 03:06 PM
Stijn is offline
Reply With Quote
I appreciate this but a few more newlines and perhaps some headers would greatly increase the readability.
Seren Seren's Avatar

JCF Member

Joined: Feb 2010

Posts: 864

Seren is a name known to allSeren is a name known to allSeren is a name known to allSeren is a name known to allSeren is a name known to allSeren is a name known to all

Jan 14, 2016, 03:18 PM
Seren is offline
Reply With Quote
Thanks for letting me know. If you have a solid idea where to insert them, by all means feel free to edit the post yourself, I won't mind. Otherwise I'll give it a go in the near future.
__________________

I am an official JJ2+ programmer and this has been an official JJ2+ statement.
Violet CLM Violet CLM's Avatar

JCF Éminence Grise

Joined: Mar 2001

Posts: 10,978

Violet CLM has disabled reputation

Jan 14, 2016, 10:20 PM
Violet CLM is offline
Reply With Quote
I agree with Stijn—also, lists! [LIST] if you want to use BBCode for everything. I also would have liked more sample code, in particular for the "!ban 5 60m airboard bug abuse" part, and some more work tying general string mechanics into stuff people might want specifically for JJ2+ purposes.
__________________
Seren Seren's Avatar

JCF Member

Joined: Feb 2010

Posts: 864

Seren is a name known to allSeren is a name known to allSeren is a name known to allSeren is a name known to allSeren is a name known to allSeren is a name known to all

Feb 9, 2016, 06:04 AM
Seren is offline
Reply With Quote
Enums

Introduction

There are certain problems in scripting that simply shouldn't be solved with use of data types already offered by AngelScript. Consider, for example, the following scenario: you're trying to write a script in which players can keep a single pet animal at their home. They have a choice between 3 available pets: a dog, cat, or gold fish. Thus, the script must somehow keep track of what pet the player chose. You probably have some idea for a variable that could accomplish that, but in this tutorial I hope to show you that the superior way to do that is by using enums.

First, let's see the flaws of the three solutions that might've come to your mind if you don't normally use enums or classes. Perhaps you thought declaring an integer variable would be a good solution:
Code:
int pet;
We can now decide that when pet equals 1, the species is a dog, when it's 2, it's a cat, and 3 means a fish. This solution works, but it's not ideal - as you can see, we have to memorize a couple of numbers and their meanings. We could define a few constants to deal with that, but if we add a lot more pets later on, that will be a lot of constants, and we'll have to make sure the numbers don't repeat. Moreover, say you make a mistake and assign a value of something like 4 to the variable pet. This obviously won't be detected as an error by the compiler because 4 is still a valid integer, but your code probably won't know how to handle it and it certainly won't know where the erroneous assignment occurred, and you'll have to debug it manually.

Another naive solution would be to declare pet as a string. This seems a bit more intuitive:
Code:
string pet;
Now we can assign something like "dog", or "cat", or "fish" to the variable, and we won't need to define any constants to make it look good. However, you still have to be careful with what you assign - perhaps even more than previously. Nothing will save you if you make a typo in one of the strings or momentarily forget whether your convention was to type "goldfish", "gold fish", or perhaps "gold_fish". The compiler will not report an error, but your code will not work as you intended. Furthermore, strings are a quite costly data type to operate on, and not supported in switch-case statements, which is a very inconvenient fact for our cause.

Finally, you may have considered Booleans. Of course one Boolean won't do, so you declare three:
Code:
bool dog;
bool cat;
bool fish;
The problems here may not be immediately obvious, but this is actually the worst of the three commonly misused solutions. First off, each time you change the pet, you have to write to all of the variables, setting one to true and the rest to false. This is simple enough if you only have 3 available pets, but once you expand to 20, your code not only starts to look like a mess, but also becomes the least efficient of the discussed solutions. Not to mention that each time you add a new pet, you have to go through your code, find each place where the pet can be changed, and add a new variable to be set to false. Additionally, this is again one of the cases where the compiler won't report an error if you forget to set something to false, but you ought to find out something is wrong when there are apparently two pet variables set to true at the same time.

As we found, all of the presented solutions have some flaws. In particular, none of them will report an error if we attempt to assign a value that we don't consider valid.

Enums

Enumerated types, enumerations, or enums for short, are a construct designed specifically to solve this sort of issues. By registering an enum, you create a new, special data type. Variables of this type will be only allowed to take values defined by the enum. Specifically, to address our pet animal problem, we could define the following enum:
Code:
enum pet_type {dog, cat, fish}
Now, pet_type is registered as a new data type whose instances can only have values of dog, cat, and fish. It's important to understand that by writing this line, we haven't actually defined any variable. That line is only a definition of a type. To define a variable, we would write the following:
Code:
pet_type pet;
Looks strange? Perhaps, but it shouldn't. It's the same as any other variable definition - type name followed by variable name. The only difference between a definition like that and something like int pet; is that now the type is one you made yourself. In fact, after pet_type was defined as an enum, it became a type as any other, and can now be used in any other expression where built-in types such as int could be used, for example as a return type or argument in function definitions:
Code:
pet_type getPetOtherThan(pet_type animal) {
	// ...
}
Let's see what we can do with this new variable. As it turns out, not a whole lot. We can assign it a new value (e.g. pet = cat;), we can compare it to other values (e.g. pet == fish), and we can very neatly use it in switch-case statements:
Code:
switch (pet) {
	case dog:
		// do something with dog
		break;
	case cat:
		// do something with cat
		break;
	case fish:
		// do something with fish
		break;
}
But that's about it. And for our purposes, it's exactly what we want. For example, we really want the line pet = 1; to cause an error, because, let's face it, numbers are not pets, and if we wrote that, we must've screwed up. Code such as pet += 2; simply makes no sense, and thus it's completely reasonable that it won't compile (as opposed to what would happen if we used an int instead). Really, all it makes sense to do with a variable like this is set it and read it, and it's not a limitation of the type that this is all that's allowed, it's what we truly expected from it.

Conversions

It may interest you how enum type variables are stored internally. After all, you were taught that it's all ones and zeroes inside your computer and now suddenly you are allowed to assign a cat to your variable. In fact, on the inside, variables declared as enum types are the same as integers, and possible values, such as dog, cat, and fish, are simply integer constants for 0, 1, and 2.

Now, I know what you're thinking, at the beginning of this tutorial I told you that using an int would be bad and registering int constants would be tiresome, and now we're doing exactly that except in a more complicated way, and you're right that there would be no difference in the effect perceived by a person running our script. The reason we use enums is that we are humans. We make errors in our code, and enums let us know about them immediately. We can read organized code more easily, and enums provide organization. We have second thoughts, and enums let us quickly expand or modify code. Enums will not extend what you can do with scripts, but they make your life as a script writer easier.

Why is knowing the internal form of enums useful? Well, turns out it's not entirely internal and you can actually do some operations involving both enums and integers. For example, I told you that the expression pet += 2; is invalid. However, pet + 2 would in fact be a valid integer. In this expression, the variable pet is first converted to an integer, for example cat would be converted to 1, and then it is added to 2, giving 3 in the result. This value cannot be assigned back to pet, because it is an integer, but it can be assigned to an integer variable. It may seem strange that this conversion is allowed, but it finds use in some instances. Indeed, enums can be defined in such a way that specific identifiers are given specific integer values. For example:
Code:
enum Quantity {one = 1, two, dozen = 12, lots = 128}
By using the equals ('=') sign, you assign the integer constant on the right to the identifier on the left. If no value is assigned, as in case of two in our example, the value used is the value of the previous term plus 1. If no value is given to the initial term, it is given the value of 0, as happened to dog in our first enum.

This feature is sometimes used to simply define a large number of related integer constants in a row, but this can be considered abuse of the enum keyword, because if you don't need the additional functionality provided by enums; you could just use a bunch of const int definitions. As for valid use cases, it mostly comes in useful if you intend to serialize1 enum types, that is, save them into a file or send over the network. The latter is unlikely to ever be an issue in JJ2+ because the game ensures that the client and the server are running the same version of the script, however files are a completely realistic concern. Consider for example that you had saved a file that stores information about a player's pet. Then you worked on the script further and extended it so that different dog and cat breeds are available. You updated the pet_type enum accordingly
Code:
enum pet_type {
	golden_retriever,
	german_shepherd,
	corgi,
	
	scottish_fold,
	maine_coon,
	ragdoll,
	
	gold_fish
}
However, there's a problem. Many players already have save files from the old version of the script and if they load it in this new script, their pets become dogs. That's because values 0, 1, and 2 saved in their files all correspond to dog breeds in this new enum. We could rearrange the enum, but then we would have to sacrifice the organization by species. Instead, we solve it by giving explicit values to the identifiers:
Code:
enum pet_type {
	golden_retriever = 0,
	german_shepherd  = 3,
	corgi            = 4,
	
	scottish_fold    = 1,
	maine_coon       = 5,
	ragdoll          = 6,
	
	gold_fish        = 2
}
Notice that if you choose to do this, you are the one responsible for making sure all integer values are different, because repeated values in enums are allowed and won't be reported as errors or even warnings. Explicit values are often given to identifiers of serialized enums even when they're in the right order, to show clearly that the values must be maintained through different versions of the script:
Code:
enum pet_type {
	dog  = 0,
	cat  = 1,
	fish = 2
}
There's one more thing you're going to need to store enum values in a file, and that is conversion from integer back to an enum type. As stated from the beginning, usually attempts to assign integers to an enum type variable will be met with an error message, which is the desired behavior. However, when necessary, it's possible to convert an integer using explicit conversion, i.e.
Code:
pet = pet_type(2);
Remember not to overuse it because this operation is unsafe. AngelScript does not clearly specify what happens if you attempt to convert an integer that does not have a corresponding enum constant, but it suggests that the operation will not cause an error, and the result will be a pet value that is not one of the valid values specified by the enum. As such, it's best to make sure the integer is in the right range before converting it. As in most cases, the explicit conversion means the programmer takes responsibility for making sure this conversion makes sense. If you're writing a script library for others to use, you may also want to take into account that due to this functionality, enum values are not guaranteed to contain a valid enum constant and you should always include a default case in your functions for when that happens.

Summary

Enums are a language feature designed to make code more organized and readable, and errors easier to detect. Enums should be used wherever a variable can have several possible states that can't be reasonably described with numbers (5 is not an animal, 12 is not a piece of furniture). Variables of enum type support assignment, comparison for equality, and usage in switch-case statements. They can also be implicitly converted to integers, and integers can be explicitly converted back, however the latter operation is unsafe. When variables of enum type are to be converted to integers or back, it's best to assign the used constants the desired value in the enum definition.

Useful link:
AngelScript documentation of enums
__________________

I am an official JJ2+ programmer and this has been an official JJ2+ statement.

Last edited by Sir Ementaler; Jun 6, 2016 at 11:03 AM.
Reply

Tags
angelscript, code

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is On

Forum Jump

All times are GMT -8. The time now is 03:43 AM.