Skip to content

v3.0.0

Choose a tag to compare

@Elektryk-Andrzej Elektryk-Andrzej released this 26 Jun 14:16

Version 3.0

It's real guys. This is a HUGE release, which means likely (definitely) all of your scripts will not function after updating. Don't worry, we will be available to help on our Discord server.

Main changes

They aren't ordered in any way, just so you know :trollface:

shelp documentation generator

Tired of constantly using shelp for every single action/variable? Fear not, for now you can generate updated documentation on your PC, with descriptions and examples directly from the plugin's source code. Run shelp GENERATE in your server console to begin.
Disclaimer: This generated documentation will not update when SE updates, you'll need to re-run the generate command.

New safety system

We are glad to introduce to you our new safety system for ScriptedEvents! Thanks to it, you don't have to worry about your script crashing the server or the script randomly stopping. It's actually really simple; a tiny delay is added after every completed action. This delay is dependent on the tick speed on your server, where one action will be executed every tick. This shouldn't affect most scripts, but if you require the most performance, you can use the !-- NOSAFETY flag to remove the delay.

Multi-line comments

It's a very simple addition, but it's surprisingly helpful for creating script documentation. To enter or exit a multi-line comment, you have to use a double hashtag (##). If you leave a single double hashtag at the beginning of the script, it will be treated as the entire script being a comment. This is easier to spot if you use our VS Code extension.

##
look at
this beautiful
multi line comment!
##

PRINT hello!

Local variables

You can now use LOCAL and LOCALPLAYERVAR actions to manage variables accessible in that script only! We recommend you always use local variables unless you want the variable to be accessible in other scripts on purpose.

Custom events

Using the new TRIGGER action, you can register your own events and subscribe to other events using the !-- CUSTOMEVENT flag.

# example script 1
!-- CUSTOMEVENT test
LOG Tested!
# example script 2
LOG Testing!
TRIGGER test
output:
> Testing!
> Tested!

Folders

Instead of having one giant folder for everything, Scripted Events will now separate everything into custom subfolders. This includes Scripts, Documentation and VariableStorage folders (and Commands folder in the future).

Action and variable reworks

Close to all actions and variables were modified in some way or another. Do not assume that if a certain action still exists, it works in the exact same way. We recommend you have a good look at the new documentation before updating your scripts.

New error system

Errors should now provide you with a lot more information and be a lot more consistent. You can also get more information about them using shelp. Here is an example of the shelp SE-108 command:

=== ERROR CODE ===
ID: SE-108
The specified event '{0}' in the 'On' config was not found!
This error occurs when an invalid event name is provided in the on Exiled config. This error can be resolved by checking for typos in the name of events and referencing Exiled's list of provided events.

Argument processing

Our new ArgumentProcessor will verify if all of the action arguments provided are of the correct type before the action is executed. Together with the new error system, this will help with finding all argument related bugs in your scripts.

Functions

Functions are reusable snippets of code, allowing you to stop copy pasting the same code over and over again in different places. These are very powerful and we aim to upgrade ScriptedEvents from being a procedural programming language to a functional programming language in the future!

Function labels

Function labels work similarly to labels, but they have a defined end. When you reach the end of a function label, the script will continue execution from the last place the function was called from. Function labels use -> and <- syntax.

# example script
LOG i'm gonna call a function
GOTO Function
LOG i left a function
STOP

-> Function
LOG i'm inside of a function
<-
output:
> i'm gonna call the function
> i'm inside of the function
> i left the function

Function scripts

Function scripts are normal scripts, but they're not to be called by a player, but rather another script. You can also provide and return values to and from a function script. When values are provided to a called script, they will be encapsulated in variables like {ARG1}, {ARG2} etc.. When variables are returned from a script, they inherit their name from the function script.

# example script
CALL GetRandomPlayer {PLAYERS} 
LOG Our random player is: {GET:RANDOM_PLAYER:NAME}
# example function script GetRandomPlayer.txt
IF {!VEXISTS:ARG1}
    ERROR {THIS} - players were not provided 
    STOP
ENDIF

LOCALPLAYERVAR SET {RANDOM_PLAYER} {LIMIT:ARG1:1}
RETURN {RANDOM_PLAYER}
output:
> Our random player is: Josh

Action decorators

Action decorators are things you put after an action, which modify the behavior of said action. There are currently 2 action decorators: $IF and $FOR.

$IF action decorator

$IF allows an action to execute only if the condition provided results in TRUE.

# example script
LOG Players: {PLAYERS}
LOG players on server $IF {PLAYERS} > 0
LOG no players on server $IF {PLAYERS} = 0
output:
> Players: 0
> no players on server

$FOR action decorator

$FOR is a decorator that will repeat an action per every player in a variable, and assigning said player to its own variable. It follows the following syntax - $FOR [singlePlayerVar] IN [loopingPlayerVar], where [singlePlayerVar] is the variable which will be assigned the player currently looping through, and [loopingPlayerVar] is the variable from which the players will be looped over.

# example script
LOG Hello, {GET:PLR:NAME}! $FOR {PLR} IN {PLAYERS}
output:
> Hello, John!
> Hello, Jack!
> Hello, Josh!

Using $IF and $FOR together

These decorators are very powerful, but what if we were to combine them? Using this syntax - $IF [condition] $FOR [singlePlayerVar] IN [loopingPlayerVar] we can run a certain action per each player, but only if the condition is met for that player.

# example script
LOG All players: {DISPLAY:PLAYERS}
LOG {GET:PLR:NAME} has low hp ({GET:PLR:HP}) $IF {GET:PLR:HP} < 40 $FOR {PLR} IN {PLAYERS}
output:
> All players: Josh, Jack, John
> Jack has low hp (37)
> John has low hp (14)

This is where the functions come in

As good as that is, there is one drawback to it; readability. Fortunately, we have a solution to that! Using function labels, we can create a function that will be called for every player, and the rest of the logic can stay inside of that function. This is how it would look like when using functions:

# example script 
LOG All players: {DISPLAY:PLAYERS}
GOTO LowHealthInfo $FOR {PLR} IN {PLAYERS} 
STOP

-> LowHealthInfo
<- $IF {GET:PLR:HP} < 40

LOG {GET:PLR:NAME} has low hp ({GET:PLR:HP}) 
<-
output:
> All players: Josh, Jack, John
> Jack has low hp (37)
> John has low hp (14)

Case insensitivity

Do you hate writing all actions and variables in UPPERCASE? Constantly juggling with shift is kind of a pain, and we know it. Fortunately, version 3.0 introduces case insensitivity for actions and variables. Of course, the "recommended" way will still be writing actions and variables in uppercase, but who cares?

log we have {players} players on the server: {display:players}
output:
> we have 3 players on the server: Josh, Jack, John

New IF "statements"

Version 3.0 introduces a new way of handling IF statements! IF action now works completely differently. Instead of stopping the script if the condition evaluates to FALSE, the script will continue executing, but actions will be blocked from running. The block will be lifted after encountering an ENDIF action. There also exists a FLIPIF action, which will flip the state of the IF block, so if action execution was blocked before, it won't be after it.

Because these are not actual statements, it means that you stack them. This is tragic since it forces people to write something known as "clean code".

# example script
!-- EVENT ChangingItem

# ev item will not be provided when player changes to an empty hand
IF {VEXISTS:EVITEM}
    LOG EVITEM exists, were good to go
FLIPIF
    LOG EVITEM does not exist, stopping the script
    STOP
ENDIF

LOG simulating work here…
output (when changing to an empty hand):
> EVITEM does not exist, stopping the script

output (when changing to a valid item):
> EVITEM exists, were good to go
> simulating work here…

Indentation

If you weren't using one of the bajillion pre-release versions of 3.0, you are probably surprised to see indentation being used in SE. How does this affect the way you have to write scripts? Well, fear not, as indentation is only just pure formatting sugar! When scripts are read and cached, all indentation is removed. It exists just so quiche eaters could have some false sense of safety.

Full Changelog

We have probably missed some stuff along these like 5 months of development, so we attached the full changelog for those brave enough to try and read it.
v2.8.0...v3.0.0