domingo, 6 de julho de 2025

UEFN Verse: Access Specifiers

Access specifiers are used to define the visibility of elements in Verse code. They can be used on classes, fields, methods, and other elements.

The <public> specifier indicates that the element is available anywhere in the code.

The <protected> specifier indicates that the element is available in the class itself and in its subclasses.

The <private> specifier indicates that the element is available within the class itself but subclasses cannot access it.

When no access specifier is used, the element uses the default <internal> specifier which indicates that the element is available in the module it is in. The next article will be about modules.

The code below is an example of a class that was created just to show the application of access specifiers in the class, fields and method. 

weapon := class<public>():

    var<protected> ammunition<public>: int = 10

    calibration<private> : float = 0.03	

    Fire<public>(): void =
        if (ammunition > 0):
            set ammunition -= 1 
            Print("Weapon fired")
        else:
            Print("No ammo")

In variables, the specifier used next to var indicates where it can be modified. The specifier used next to the variable name indicates where it can be accessed. In the example above, the variable ammunition can be accessed anywhere but can only be modified within the class itself and its subclasses.

Consider WeaponInstance an instance of the weapon class that is being used inside another class. The following accesses are valid because the elements are <public>:

Print("{WeaponInstance.ammunition}")
WeaponInstance.Fire()

The accesses below are invalid because calibration is <private> and the var of ammunition is <protected>:

Print("{WeaponInstance.calibration}")
set WeaponInstance.ammunition = 15

The code below creates the rifle_grenade subclass using weapon as the superclass. The grenades variable is using the default access specifier which is <internal>.

rifle_grenade := class<public>(weapon):

    var grenades: int = 3

    LaunchGrenade<public>():void =
        if (grenades > 0):
            set grenades -= 1 
            Print("Grenade launched")
        else:
            Print("No grenade")

    RifleStatus<public>():void =
        Print("ammunition: {ammunition} | grenades: {grenades}")

In the RifleStatus() method we can see that the ammunition variable of the weapon superclass is accessible. It can also be modified in the subclass.

The calibration variable is not accessible in the rifle_grenade subclass because it is <private>.

The code below shows these example classes in a single file so you can test them on UEFN. I created a verse device called access_specifiers_device and used this code:

using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }

weapon := class<public>():

    var<protected> ammunition<public>: int = 10

    calibration<private> : float = 0.03	

    Fire<public>(): void =
        if (ammunition > 0):
            set ammunition -= 1 
            Print("Weapon fired")
        else:
            Print("No ammo")

rifle_grenade := class<public>(weapon):

    var grenades: int = 3

    LaunchGrenade<public>():void =
        if (grenades > 0):
            set grenades -= 1 
            Print("Grenade launched")
        else:
            Print("No grenade")

    RifleStatus<public>():void =
        Print("ammunition: {ammunition} | grenades: {grenades}")

access_specifiers_device := class(creative_device):

    RifleGrenade : rifle_grenade = rifle_grenade{}

    OnBegin<override>()<suspends>:void= 

        Print("{RifleGrenade.ammunition}")
        RifleGrenade.Fire()
        RifleGrenade.LaunchGrenade()
        RifleGrenade.RifleStatus()

This Verse device creates an instance of the rifle_grenade class and accesses the ammunition variable and the Fire() method of the weapon superclass and two more methods of the rifle_grenade class.


UEFN Verse: Especificadores de acesso

Os especificadores de acesso são usados para definir a visibilidade de elementos no código Verse. Eles podem ser usados em classes, campos, métodos e outros elementos.

O especificador <public> indica que o elemento está disponível em qualquer parte do código. 

O especificador <protected> indica que o elemento está disponível na própria classe e em suas subclasses.

O especificador <private> indica que o elemento está disponível na própria classe mas as subclasses não conseguem acessar.

Quando não é usado um especificador de acesso, o elemento usa o especificador padrão que é o <internal> que indica que o elemento está disponível no módulo em que ele está. O próximo artigo será sobre módulos. 

O código abaixo é um exemplo de classe que foi criada apenas para mostrar a aplicação dos especificadores de acesso na classe, em campos e no método. 

weapon := class<public>():

    var<protected> ammunition<public>: int = 10

    calibration<private> : float = 0.03	

    Fire<public>(): void =
        if (ammunition > 0):
            set ammunition -= 1 
            Print("Weapon fired")
        else:
            Print("No ammo")

Nas variáveis o especificador usado ao lado de var indica onde ela pode ser modificada. O especificador usado ao lado no nome da variável indica onde ela pode ser acessada. No exemplo acima a variável ammunition pode ser acessada em qualquer lugar mas só pode ser modificada na própria classe e nas subclasses.

Considere WeaponInstance uma instância da classe weapon que está sendo usada dentro de outra classe. Os acessos abaixo são válidos porque os elementos são <public>:

Print("{WeaponInstance.ammunition}")
WeaponInstance.Fire()

Os acessos abaixo são inválidos porque calibration é <private> e o var de ammunition é <protected>:

Print("{WeaponInstance.calibration}")
set WeaponInstance.ammunition = 15

O código abaixo cria a subclasse rifle_grenade usando weapon como superclasseA variável grenades está usando o especificador de acesso default que é o <internal>.

rifle_grenade := class<public>(weapon):

    var grenades: int = 3

    LaunchGrenade<public>():void =
        if (grenades > 0):
            set grenades -= 1 
            Print("Grenade launched")
        else:
            Print("No grenade")

    RifleStatus<public>():void =
        Print("ammunition: {ammunition} | grenades: {grenades}")

No método RifleStatus() podemos ver que a variável ammunition da superclasse weapon é acessível. Ela também pode ser modificada na subclasse.

A variável calibration não é acessível na subclasse rifle_grenade porque ela é <private>.

O código abaixo mostra estas classes de exemplo em um único arquivo para poder testar no UEFN. Eu criei um dispositivo verse chamado access_specifiers_device e usei este código:
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }

weapon := class<public>():

    var<protected> ammunition<public>: int = 10

    calibration<private> : float = 0.03	

    Fire<public>(): void =
        if (ammunition > 0):
            set ammunition -= 1 
            Print("Weapon fired")
        else:
            Print("No ammo")

rifle_grenade := class<public>(weapon):

    var grenades: int = 3

    LaunchGrenade<public>():void =
        if (grenades > 0):
            set grenades -= 1 
            Print("Grenade launched")
        else:
            Print("No grenade")

    RifleStatus<public>():void =
        Print("ammunition: {ammunition} | grenades: {grenades}")

access_specifiers_device := class(creative_device):

    RifleGrenade : rifle_grenade = rifle_grenade{}

    OnBegin<override>()<suspends>:void= 

        Print("{RifleGrenade.ammunition}")
        RifleGrenade.Fire()
        RifleGrenade.LaunchGrenade()
        RifleGrenade.RifleStatus()

Este dispositivo Verse cria uma instância da classe rifle_grenade e acessa a variável ammunition e o método Fire() da superclasse weapon e mais dois métodos da própria classe rifle_grenade.


quarta-feira, 2 de julho de 2025

UEFN Verse: Class Specifiers

Class specifiers are used when creating classes to define behaviors and characteristics. This article will present the main ones.

The <abstract> specifier is used to create superclasses with common fields and methods to be inherited by subclasses.

An abstract class allows the declaration of methods without a body (it has no code) that must be overridden in a subclass.

The code below creates the abstract class base_bonus. The ApplyBonus() method has no body.

base_bonus := class<abstract>():
    BonusId : int
    Name : string 
    BonusValue: int
	
    BonusData(): string =
        "BonusId: {BonusId} | Name: {Name} | BonusValue: {BonusValue}"

    ApplyBonus() : void

It is not possible to create instances of an abstract class. The code below generates a compilation error.

BaseBonus : base_bonus = base_bonus{BonusValue := 20,  Name := "Generic"}


The <concrete> specifier indicates that all fields of the class must have default values, allowing the creation of instances with an empty archetype.

The code below creates the concrete class score_bonus using base_bonus as the superclass. All fields have been given default values ​​and the ApplyBonus() method has been overridden.

score_bonus := class<concrete>(base_bonus):
    BonusId<override> : int = 2
    Name<override> : string = "Score MEDIUM"
    BonusValue<override>: int = 50
	
    ApplyBonus<override>() : void =
        Print("Adding {BonusValue} to SCORE.")

This code creates an instance of score_bonus using an empty archetype {}.

ScoreBonusDefault : score_bonus = score_bonus{}


The <final> specifier is used to indicate that a class cannot have subclasses. This specifier can also be used on fields and methods to indicate that they cannot be overridden.

The code below creates the final class time_bonus using base_bonus as the superclass.

time_bonus := class<final>(base_bonus):
    BonusId<override> : int = 1
	
    ApplyBonus<override>() : void =
        Print("Adding {BonusValue} to TIME.")

The new time_bonus class cannot be used as a superclass. The following code generates a compilation error.

time_bonus_variation := class(time_bonus):


Let's combine these examples into a single file so we can test it on UEFN. I created a verse device called class_specifiers_device and used this code:

using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }

base_bonus := class<abstract>():
    BonusId : int
    Name : string 
    BonusValue: int
	
    BonusData(): string =
        "BonusId: {BonusId} | Name: {Name} | BonusValue: {BonusValue}"

    ApplyBonus() : void

time_bonus := class<final>(base_bonus):
    BonusId<override> : int = 1
	
    ApplyBonus<override>() : void =
        Print("Adding {BonusValue} to TIME.")

score_bonus := class<concrete>(base_bonus):
    BonusId<override> : int = 2
    Name<override> : string = "Score MEDIUM"
    BonusValue<override>: int = 50
	
    ApplyBonus<override>() : void =
        Print("Adding {BonusValue} to SCORE.")		

class_specifiers_device := class(creative_device):

    TimeBonus : time_bonus = time_bonus{BonusValue := 30, Name := "Time MEDIUM"}

    ScoreBonusDefault : score_bonus = score_bonus{}

    OnBegin<override>()<suspends>:void= 

        Print( ScoreBonusDefault.BonusData() )
        ScoreBonusDefault.ApplyBonus()

This Verse device simply executes the two methods of the ScoreBonusDefault instance to write some messages to the log. The device was created to illustrate the use of class specifiers. 


Table of Contents Verse


UEFN Verse: Especificadores de classe

Os especificadores de classe são usados na criação das classes para definir comportamentos e características. Neste artigo serão apresentados os principais.

O especificador <abstract> é usado para criar superclasses com campos e métodos comuns para serem herdados por subclasses.

Uma classe abstrata permite a declaração de métodos sem corpo (não possui código) que devem ser sobrescritos em uma subclasse.

O código abaixo cria a classe abstrata base_bonus. O método ApplyBonus() não tem corpo.

base_bonus := class<abstract>():
    BonusId : int
    Name : string 
    BonusValue: int
	
    BonusData(): string =
        "BonusId: {BonusId} | Name: {Name} | BonusValue: {BonusValue}"

    ApplyBonus() : void

Não é possivel criar instâncias de uma classe abstrata. O código abaixo gera um erro de compilação.

BaseBonus : base_bonus = base_bonus{BonusValue := 20,  Name := "Generic"}


O especificador <concrete> indica que todos os campos da classe tem de ter valores default permitindo a criação de instâncias com um arquétipo vazio.

O código abaixo cria a classe concreta score_bonus usando base_bonus como superclasse. Todos os campos receberam valores default e o método ApplyBonus() foi sobrescrito.

score_bonus := class<concrete>(base_bonus):
    BonusId<override> : int = 2
    Name<override> : string = "Score MEDIUM"
    BonusValue<override>: int = 50
	
    ApplyBonus<override>() : void =
        Print("Adding {BonusValue} to SCORE.")

Este código cria uma instância de score_bonus usando um arquétipo vazio {}.

ScoreBonusDefault : score_bonus = score_bonus{}


O especificador <final> é usado para indicar que uma classe não pode ter subclasses. Este especificador também pode ser usado em campos e métodos para indicar que eles não podem ser sobrescritos.

O código abaixo cria a classe final time_bonus usando base_bonus como superclasse.

time_bonus := class<final>(base_bonus):
    BonusId<override> : int = 1
	
    ApplyBonus<override>() : void =
        Print("Adding {BonusValue} to TIME.")

A nova classe time_bonus não pode ser usada como superclasse. O código a seguir gera um erro de compilação.

time_bonus_variation := class(time_bonus):


Vamos juntar estes exemplos em um único arquivo para poder testar no UEFN. Eu criei um dispositivo verse chamado class_specifiers_device e usei este código:

using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }

base_bonus := class<abstract>():
    BonusId : int
    Name : string 
    BonusValue: int
	
    BonusData(): string =
        "BonusId: {BonusId} | Name: {Name} | BonusValue: {BonusValue}"

    ApplyBonus() : void

time_bonus := class<final>(base_bonus):
    BonusId<override> : int = 1
	
    ApplyBonus<override>() : void =
        Print("Adding {BonusValue} to TIME.")

score_bonus := class<concrete>(base_bonus):
    BonusId<override> : int = 2
    Name<override> : string = "Score MEDIUM"
    BonusValue<override>: int = 50
	
    ApplyBonus<override>() : void =
        Print("Adding {BonusValue} to SCORE.")		

class_specifiers_device := class(creative_device):

    TimeBonus : time_bonus = time_bonus{BonusValue := 30, Name := "Time MEDIUM"}

    ScoreBonusDefault : score_bonus = score_bonus{}

    OnBegin<override>()<suspends>:void= 

        Print( ScoreBonusDefault.BonusData() )
        ScoreBonusDefault.ApplyBonus()

Este dispositivo Verse apenas executa os dois métodos da instância ScoreBonusDefault para escrever algumas mensagens no log. O dispositivo foi criado para ilustrar o uso dos especificadores de classe. 


Sumário Verse


terça-feira, 24 de junho de 2025

UEFN Verse: Class inheritance and <override>

Class inheritance is a fundamental concept for understanding Verse programming in UEFN.

To create a creative device in Verse, you need to create a subclass of the creative_device class. The new class will inherit the fields (constants and variables) and methods (functions) of the creative_device class that is used as a superclass as shown in the following line:

inheritance_device := class(creative_device):

The superclass is also known as the parent class or base class. The subclass is the child class.

The example below shows a base_bonus class with three fields and two methods. The base_bonus class is used as a superclass in the creation of the time_bonus class which will inherit the three fields and two methods of base_bonus.

base_bonus := class:
    BonusId : int = 1
    Name : string 
    BonusValue: int
	
    BonusData(): string =
        "BonusId: {BonusId} | Name: {Name} | BonusValue: {BonusValue}"

    ApplyBonus() : void =
        Print("Adding {BonusValue} to SCORE.")

time_bonus := class(base_bonus):
    BonusId<override> : int = 2
	
    ApplyBonus<override>() : void =
        Print("Adding {BonusValue} to TIME.")

The <override> specifier is being used to be able to initialize the BonusId field with a different value than the value used in the superclass. It is also being used to create a new version of the ApplyBonus()method in the time_bonus class.

Let's create a device in UEFN that uses the classes base_bonus and time_bonus. In any UEFN project, open Verse Explorer, right-click on the project name and choose the Add new Verse file to project option.

In Device Name put inheritance_device and click the Create Empty button.

This device has an array to store references to base_bonus instances. The array is initialized with instances of base_bonus and time_bonus. This is possible because an instance of time_bonus is also of type base_bonus.

Copy the Verse code below into the inheritance_device file:

using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }

base_bonus := class:
    BonusId : int = 1
    Name : string 
    BonusValue: int
	
    BonusData(): string =
        "BonusId: {BonusId} | Name: {Name} | BonusValue: {BonusValue}"

    ApplyBonus() : void =
        Print("Adding {BonusValue} to SCORE.")

time_bonus := class(base_bonus):
    BonusId<override> : int = 2
	
    ApplyBonus<override>() : void =
        Print("Adding {BonusValue} to TIME.")

inheritance_device := class(creative_device):

    BonusArray : []base_bonus = array{ base_bonus{BonusValue := 50,  Name := "Score MEDIUM"},
				       base_bonus{BonusValue := 100, Name := "Score MAX"},
				       time_bonus{BonusValue := 30, Name := "Time MEDIUM"},
				       time_bonus{BonusValue := 60, Name := "Time MAX"} }

    OnBegin<override>()<suspends>:void=

        for (Bonus : BonusArray):
            Print( Bonus.BonusData() )
            Bonus.ApplyBonus()

In the OnBegin method, the for loop is being used to iterate through all the elements of the array. For each element, the BonusData() and ApplyBonus() methods are executed. If the instance is of the time_bonus type, the version of ApplyBonus() that was overridden in the time_bonus class will be executed.

Save the file and compile the Verse code using the Verse > Build Verse Code option from the UEFN menu.

Access the Content Drawer and add the inheritance_device to the level.

Click the Launch Session button located in the UEFN toolbar to load the level into Fortnite. 

After starting the session in Fortnite, press the Tab key and select the Log tab to view the log with the messages written by the Print functions.


Table of Contents Verse


UEFN Verse: Herança de classe e <override>

Herança de classe é um conceito fundamental para entender a programação em Verse no UEFN. 

Para criar um dispositivo criativo no Verse, é preciso criar uma subclasse da classe creative_device. A nova classe herdará os campos (constantes e variáveis) e métodos (funções) da classe creative_device que é usada como superclasse como mostra a linha a seguir:

inheritance_device := class(creative_device):

A superclasse também é conhecida como classe pai ou classe base. A subclasse é a classe filha.

O exemplo abaixo mostra uma classe base_bonus com três campos e dois métodos. A classe base_bonus é usada como superclasse na criação da classe time_bonus que herdará os três campos e dois métodos de base_bonus.

base_bonus := class:
    BonusId : int = 1
    Name : string 
    BonusValue: int
	
    BonusData(): string =
        "BonusId: {BonusId} | Name: {Name} | BonusValue: {BonusValue}"

    ApplyBonus() : void =
        Print("Adding {BonusValue} to SCORE.")

time_bonus := class(base_bonus):
    BonusId<override> : int = 2
	
    ApplyBonus<override>() : void =
        Print("Adding {BonusValue} to TIME.")

O especificador <override> está sendo usado para poder inicializar o campo BonusId com um valor diferente do valor usado na superclasse. Ele também está sendo usado para criar uma nova versão do método ApplyBonus() na classe time_bonus.

Vamos criar um dispositivo no UEFN que usa as classes base_bonus e time_bonusEm qualquer projeto UEFN, abra o Verse Explorer, clique com o botão-direito no nome do projeto e escolha a opção Add new Verse file to project.

Em Device Name coloque inheritance_device clique no botão Create Empty.

Este dispositivo possui um array para armazenar referências às instâncias de base_bonus. O array é inicializado com instâncias de base_bonus e de time_bonus. Isto é possível porque uma instância de time_bonus também é do tipo base_bonus.

Copie o código Verse abaixo para o dispositivo inheritance_device:

using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }

base_bonus := class:
    BonusId : int = 1
    Name : string 
    BonusValue: int
	
    BonusData(): string =
        "BonusId: {BonusId} | Name: {Name} | BonusValue: {BonusValue}"

    ApplyBonus() : void =
        Print("Adding {BonusValue} to SCORE.")

time_bonus := class(base_bonus):
    BonusId<override> : int = 2
	
    ApplyBonus<override>() : void =
        Print("Adding {BonusValue} to TIME.")

inheritance_device := class(creative_device):

    BonusArray : []base_bonus = array{ base_bonus{BonusValue := 50,  Name := "Score MEDIUM"},
				       base_bonus{BonusValue := 100, Name := "Score MAX"},
				       time_bonus{BonusValue := 30, Name := "Time MEDIUM"},
				       time_bonus{BonusValue := 60, Name := "Time MAX"} }

    OnBegin<override>()<suspends>:void=

        for (Bonus : BonusArray):
            Print( Bonus.BonusData() )
            Bonus.ApplyBonus()

No método OnBegin está sendo usado o laço for para percorrer todos os elementos do array. Para cada elemento são executados os métodos BonusData() e ApplyBonus(). Se a instância for do tipo time_bonus, será executada a versão do ApplyBonus() que foi sobrescrita na classe time_bonus.

Salve o arquivo e compile o código Verse usando a opção Verse > Build Verse Code do menu do UEFN. 

Acesse o Content Drawer e adicione o dispositivo Verse inheritance_device ao nível. 

Clique no botão Launch Session localizado na barra de ferramentas do UEFN para carregar o nível no Fortnite. 

Após iniciar a partida no Fortnite, pressione a tecla Tab e selecione a aba Registro para visualizar o log com as mensagens escritas pelas funções Print.


Sumário Verse


sexta-feira, 6 de junho de 2025

UEFN Verse: Introduction to specifiers

Specifiers are used in the Verse language to define behaviors for some Verse elements. The symbols < and > are used by specifiers. The OnBegin function, present in Verse devices, has two specifiers: override and suspends. 

    OnBegin<override>()<suspends>:void=

The <override> specifier indicates that the OnBegin function is overriding the OnBegin function of the parent class creative_device. We will look at the <override> specifier in more detail in an article on class inheritance.

The <suspends> specifier is used to define asynchronous functions that execute in parallel. This means that they can be suspended and then resumed to continue their execution.

Another common specifier is <decides> used to create failable expressions. You can generate a failure inside the function by using the expression false? .

If you create a function using only the <decides> specifier, when you try to call the function you will get a compilation error with the following message:

"This invocation calls a function that has the 'no_rollback' effect, which is not allowed by its context."

To avoid this error, you can use the <transacts> specifier which indicates that expressions executed inside the function can be rolled back.

The line below shows an example of a function declaration using <decides> and <transacts>:

    IncreaseExperience(Points: int)<decides><transacts>:void=


Let's create a device in UEFN applying these specifiers. In any UEFN project, open Verse Explorer, right-click on the project name and choose the Add new Verse file to project option.

In Device Name put specifiers_device and click the Create Empty button.

This device will call the IncreaseExperience function once per second, passing in a different value that will be added to a variable called ExperiencePoints. There is a 1 in 6 chance that the IncreaseExperience function will fail. If it fails, the ExperiencePoints variable will roll back its value.

Copy the Verse code below into the specifiers_device file:

using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /Verse.org/Random }

specifiers_device := class(creative_device):
    
    var ExperiencePoints : int = 0

    OnBegin<override>()<suspends>:void=

        var XpGain : int = 0
        
        loop:
            set XpGain += 1

            if( IncreaseExperience[XpGain] ):
                Print("XpGain is valid")
            else:
                Print("*** XpGain is INVALID ***") 
                Print("ExperiencePoints rolled back to {ExperiencePoints}")

            Sleep(1.0)

    IncreaseExperience(Points: int)<decides><transacts>:void=

        set ExperiencePoints += Points
        Print("ExperiencePoints set to {ExperiencePoints}")

        if( GetRandomInt(1, 6) = 1 ):
            false?   #this is a failure

Note that in the OnBegin function, a loop is being used without a break or return expression to exit the loop. The loop repeats the expressions in its code block, and the Sleep() function suspends the OnBegin function for a second.

The IncreaseExperience function is a failable function due to the use of <decides>, so we use [ ] instead of ( ) in the call.

The GetRandomInt() function generates a random number between two numbers. The numbers used as parameters can be part of the result. To use this function, you need to include the Verse.org/Random module at the beginning of the file.

Save the file and compile the Verse code using the Verse > Build Verse Code option from the UEFN menu.

Access the Content Drawer and add the specifiers_device to the level.

Click the Launch Session button located in the UEFN toolbar to load the level into Fortnite. 

After starting the session in Fortnite, press the Tab key and select the Log tab to view the log with the messages written by the Print functions.


Table of Contents Verse