sábado, 28 de outubro de 2023

UEFN Verse: Final version of round_based_device

This is the last article in Part II. Let's add the Verse code that controls the Guard Spawner devices.

The Guard Spawner device references will be stored in an array. Add the array declaration after the RoundDevice variables. 

    @editable
    GuardSpawners : []guard_spawner_device = array{}


Enabling Guard Spawner devices according to the current round is done in a similar way to Capture Area devices. Add the EnableGuardSpawners function below that receives as a parameter the number of Guard Spawners that must be enabled.

    EnableGuardSpawners(NumberOfSpawners:int):void=        

        MaxIndex := NumberOfSpawners - 1

        for (Index := 0..MaxIndex):
            if(GuardSpawner := GuardSpawners[Index]):
                GuardSpawner.Enable()                


The EnableGuardSpawners function will be called during round setup. It receives the CurrentRound variable as a parameter. The code below shows how the Round1Setup function will look like. Do the same for the other round setup functions.

    Round1Setup():void=
        set CurrentRound = 1
        
        EnableCaptureAreas(CurrentRound)
        EnableGuardSpawners(CurrentRound)


With these changes we complete the Verse code for round_based_device. I decided to make a simple game to keep the focus on the round setup functions that are associated with the Round Settings devices. Within these functions you have countless possibilities for creating different rounds.

The Verse code for the final version of round_based_device looks like this:

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

round_based_device := class(creative_device):

    @editable
    EndGameDevice : end_game_device = end_game_device{}

    @editable 
    CaptureAreas: []capture_area_device = array{}

    var NumberOfAreasCaptured : int = 0

    var CurrentRound : int = 0

    @editable
    Round1Device : round_settings_device = round_settings_device{}

    @editable
    Round2Device : round_settings_device = round_settings_device{}

    @editable
    Round3Device : round_settings_device = round_settings_device{}

    @editable
    Round4Device : round_settings_device = round_settings_device{}

    @editable
    Round5Device : round_settings_device = round_settings_device{}

    @editable
    GuardSpawners : []guard_spawner_device = array{}

    OnBegin<override>()<suspends>:void=
        Round1Device.RoundBeginEvent.Subscribe(Round1Setup)
        Round2Device.RoundBeginEvent.Subscribe(Round2Setup)
        Round3Device.RoundBeginEvent.Subscribe(Round3Setup)
        Round4Device.RoundBeginEvent.Subscribe(Round4Setup)
        Round5Device.RoundBeginEvent.Subscribe(Round5Setup)

    AreaCaptured(Agent:agent):void=
        set NumberOfAreasCaptured += 1

        if( NumberOfAreasCaptured = CurrentRound):
            EndGameDevice.Activate(Agent)

    EnableCaptureAreas(NumberOfAreas:int):void=        
        MaxIndex := NumberOfAreas - 1

        for (Index := 0..MaxIndex):
            if(Area := CaptureAreas[Index]):
                Area.Enable()
                Area.AreaIsScoredEvent.Subscribe(AreaCaptured)

    EnableGuardSpawners(NumberOfSpawners:int):void=        

        MaxIndex := NumberOfSpawners - 1

        for (Index := 0..MaxIndex):
            if(GuardSpawner := GuardSpawners[Index]):
                GuardSpawner.Enable()                
            
    Round1Setup():void=
        set CurrentRound = 1
        
        EnableCaptureAreas(CurrentRound)
        EnableGuardSpawners(CurrentRound)
                            
    Round2Setup():void=
        set CurrentRound = 2
        
        EnableCaptureAreas(CurrentRound)
        EnableGuardSpawners(CurrentRound)

    Round3Setup():void=
        set CurrentRound = 3
        
        EnableCaptureAreas(CurrentRound)
        EnableGuardSpawners(CurrentRound)
     
    Round4Setup():void=
        set CurrentRound = 4
        
        EnableCaptureAreas(CurrentRound)
        EnableGuardSpawners(CurrentRound)

    Round5Setup():void=
        set CurrentRound = 5
        
        EnableCaptureAreas(CurrentRound)
        EnableGuardSpawners(CurrentRound)
    


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

Select the round_based_device in the level. In the Details tab, add 5 elements to the GuardSpawners array and select the Guard Spawners device references:


Save the level and start the session. Each round, another Guard Spawner will be enabled, which will spawn 2 guards.



It will be difficult to complete the last rounds. I'll give you some tips:
  • Use the Verse device that is in the level to hide and protect yourself from gunfire.
  • When capturing an area, stay crouched and moving to avoid the guards' shots.
  • Try to eliminate one of the guards and run to get the rifle he drops.


I hope this example helps you in learning and practicing the Verse language. We still have a long way to go.


Table of Contents Verse


UEFN Verse: Versão final do round_based_device

Este é o último artigo da Parte II. Vamos adicionar o código Verse que controla os dispositivos Guard Spawner.

As referências dos dispositivos Guard Spawner serão armazenadas em um array. Adicione a declaração do array depois das variáveis RoundDevice. 

    @editable
    GuardSpawners : []guard_spawner_device = array{}


A habilitação dos dispositivos Guard Spawner conforme o round atual é feita de uma forma semelhante ao dos dispositivos Capture Area. Adicione a função EnableGuardSpawners abaixo que recebe como parâmetro o número de Guard Spawners que devem ser habilitados.

    EnableGuardSpawners(NumberOfSpawners:int):void=        

        MaxIndex := NumberOfSpawners - 1

        for (Index := 0..MaxIndex):
            if(GuardSpawner := GuardSpawners[Index]):
                GuardSpawner.Enable()                


A função EnableGuardSpawners será chamada durante o setup dos rounds. Ela recebe a variável CurrentRound como parâmetro. O código abaixo mostra como vai ficar a função Round1Setup. Faça o mesmo para as outras funções de setup dos rounds.

    Round1Setup():void=
        set CurrentRound = 1
        
        EnableCaptureAreas(CurrentRound)
        EnableGuardSpawners(CurrentRound)


Com estes ajustes completamos o código Verse do round_based_device. Eu decidi fazer um jogo simples para manter o foco nas funções de setup dos rounds que estão associadas aos dispositivos Round Settings. Dentro dessas funções você tem inúmeras possibilidades para a criação de rounds diferenciados.

O código Verse da versão final do round_based_device fica assim:

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

round_based_device := class(creative_device):

    @editable
    EndGameDevice : end_game_device = end_game_device{}

    @editable 
    CaptureAreas: []capture_area_device = array{}

    var NumberOfAreasCaptured : int = 0

    var CurrentRound : int = 0

    @editable
    Round1Device : round_settings_device = round_settings_device{}

    @editable
    Round2Device : round_settings_device = round_settings_device{}

    @editable
    Round3Device : round_settings_device = round_settings_device{}

    @editable
    Round4Device : round_settings_device = round_settings_device{}

    @editable
    Round5Device : round_settings_device = round_settings_device{}

    @editable
    GuardSpawners : []guard_spawner_device = array{}

    OnBegin<override>()<suspends>:void=
        Round1Device.RoundBeginEvent.Subscribe(Round1Setup)
        Round2Device.RoundBeginEvent.Subscribe(Round2Setup)
        Round3Device.RoundBeginEvent.Subscribe(Round3Setup)
        Round4Device.RoundBeginEvent.Subscribe(Round4Setup)
        Round5Device.RoundBeginEvent.Subscribe(Round5Setup)

    AreaCaptured(Agent:agent):void=
        set NumberOfAreasCaptured += 1

        if( NumberOfAreasCaptured = CurrentRound):
            EndGameDevice.Activate(Agent)

    EnableCaptureAreas(NumberOfAreas:int):void=        
        MaxIndex := NumberOfAreas - 1

        for (Index := 0..MaxIndex):
            if(Area := CaptureAreas[Index]):
                Area.Enable()
                Area.AreaIsScoredEvent.Subscribe(AreaCaptured)

    EnableGuardSpawners(NumberOfSpawners:int):void=        

        MaxIndex := NumberOfSpawners - 1

        for (Index := 0..MaxIndex):
            if(GuardSpawner := GuardSpawners[Index]):
                GuardSpawner.Enable()                
            
    Round1Setup():void=
        set CurrentRound = 1
        
        EnableCaptureAreas(CurrentRound)
        EnableGuardSpawners(CurrentRound)
                            
    Round2Setup():void=
        set CurrentRound = 2
        
        EnableCaptureAreas(CurrentRound)
        EnableGuardSpawners(CurrentRound)

    Round3Setup():void=
        set CurrentRound = 3
        
        EnableCaptureAreas(CurrentRound)
        EnableGuardSpawners(CurrentRound)
     
    Round4Setup():void=
        set CurrentRound = 4
        
        EnableCaptureAreas(CurrentRound)
        EnableGuardSpawners(CurrentRound)

    Round5Setup():void=
        set CurrentRound = 5
        
        EnableCaptureAreas(CurrentRound)
        EnableGuardSpawners(CurrentRound)
    


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

Selecione o round_based_device no nível. Na aba Detailsadicione 5 elementos no array GuardSpawnersselecione as referências dos dispositivos Guard Spawners:


Salve o nível e inicie a sessão. A cada round será habilitado mais um Guard Spawner que irá gerar 2 guardas.



Vai ficar difícil concluir os últimos rounds. Vou dar algumas dicas:

  • Use o dispositivo Verse que está no nível para se esconder e se proteger dos tiros.
  • Quando estiver capturando uma área, fique agachado e se movendo para evitar os tiros dos guardas.
  • Tente eliminar um dos guardas e corra para pegar o rifle que ele deixa cair.


Espero que este exemplo ajude vocês no aprendizado e prática da linguagem Verse. Ainda temos um longo caminho pela frente. 


Sumário Verse


UEFN Verse: Guard Spawner device

The Guard Spawner device can spawn a group of enemies to attack players. We can define the type of guard, the quantity and the frequency.

Our game will have 5 Guard Spawner devices. Each device will spawn two guards. The number of enabled Guard Spawner devices corresponds to the current round.

Let's add a Guard Spawner device and make the changes. Then we will make 4 copies of this Guard Spawner.

Go to the Content Drawer and the Fortnite > Devices folder. Search by guard. Drag the Guard Spawner device and drop it onto the level in the grid line above the line that has Capture Areas 4 and 5.


The image below shows the guard types available on the Guard Spawner device:


In the Details tab, choose one of the guard types and uncheck the Enabled at Game Start property: 



In our game, each Guard Spawner device will only spawn 2 guards. The guards will be part of the Team Index 2 so they will consider the player as an opponent  because the player is on the Team Index 1.

Uncheck the Allow Infinite Spawn property. Set the value 2 to Total Spawn Limit. In Guard Team Index put Team Index 2. Uncheck the Show Spawn Radius property to improve the level's visualization during editing. 


We will reduce the visibility of the guards to allow the player to capture some areas without the guards noticing.

In Visibility Range put the value 20. Change Visibility Range Restriction to Always.


Make 4 copies of the Guard Spawner device and place them on the same grid line as shown at the top of this image:


Modify the Guard Type on each of the Guard Spawners to have a variety of enemies in the game.

In the next article we will see how Guard Spawners devices will be enabled by Verse code according to the current round. If you want to test, you can manually enable some Guard Spawners by checking the Enabled at Game Start property.


Table of Contents Verse


UEFN Verse: Dispositivo Guard Spawner

O dispositivo Guard Spawner pode gerar um grupo de inimigos para atacar os jogadores. Podemos definir o tipo de guarda, a quantidade e a periodicidade.

O nosso jogo terá 5 dispositivos Guard Spawner. Cada um dos dispositivo irá gerar dois guardas. O número de dispositivos Guard Spawner habilitados corresponde ao round atual.

Vamos adicionar um dispositivo Guard Spawner e fazer as modificações. Depois faremos as 4 cópias deste Guard Spawner.  

Acesse o Content Drawer e a pasta Fortnite > Devices. Pesquise por guard. Arraste o dispositivo Guard Spawner e solte no nível na linha da grade acima da linha que tem as Capture Areas 4 e 5. 


A imagem abaixo mostrar os tipos de guardas disponíveis no dispositivo Guard Spawner:


Na aba Details, escolha um dos tipos de guarda e desmarque a propriedade Enabled at Game Start



Em nosso jogo, cada dispositivo Guard Spawner irá gerar apenas 2 guardas. Os guardas farão parte do time com índice 2 para que eles considerem o jogador como inimigo pois o jogador está no time com índice 1.

Desmarque a propriedade Allow Infinite Spawn. Coloque o valor 2 em Total Spawn Limit. Em Guard Team Index coloque Team Index 2. Desmarque a propriedade Show Spawn Radius para melhorar a visualização do nível durante a edição. 


Vamos reduzir a visibilidade dos guardas para permitir que o jogador consiga capturar alguma áreas sem que os guardas percebam.

Em Visibility Range coloque o valor 20. Mude Visibility Range Restriction para Always.


Faça 4 cópias do dispositivo Guard Spawner e coloque-os na mesma linha da grade como mostra a parte superior desta imagem:


Modifique o Guard Type em cada um dos Guard Spawners para termos variedade de inimigos no jogo.

No próximo artigo veremos como os dispositivos Guard Spawners serão habilitados por código Verse conforme o round atual. Se quiser fazer um teste, você pode habilitar manualmente alguns Guard Spawners marcando a propriedade Enabled at Game Start.


Sumário Verse


sexta-feira, 27 de outubro de 2023

UEFN Verse: Class Designer device

The Class Designer device is used to define a player class with specific attributes and equipment. It can be used in team games where each player has a role. The selection of classes within the game can be done using a Class Selector device.

In our project we will only use one Class Designer device to define the player's initial weapon and shield. We will modify the Island Settings to indicate that the player will use the new class.

Access the Content Drawer and the Fortnite > Devices folder. Search by class: 



Drag the Class Designer and drop it on the level near the Round Settings devices. In the Details tab, you can change the class name and description. Change Class Identifier to Class Slot 1:


In the Item List array you add the items that the player will have when he receives this class. In our game we will only give one pistol.

Click the + button in the Item List row to add an item to the array. Click on the small arrow next to Index [ 0 ] to access the item's properties. Click on the Item Definition dropdown and select one of the available pistols. 


In this class the player will receive the full shield. Check the Starting Shield Percentage property and enter the value 100:


The next step is to update the Island Settings so that the player can use the new class we created with the Class Designer.

Access the Outliner tab and click on IslandSettings0. In the Details tab, User Options - Game Rules category, change Default Class Identifier to Class Slot 1:



Save the level and start the session. Note when starting the game that the player will already have a pistol and his shield will be full.

In the next article we will use Guard Spawner devices to create challenges for the player.


Table of Contents Verse


UEFN Verse: Dispositivo Class Designer

O dispositivo Class Designer é usado para definir uma classe de jogador com atributos e equipamentos específicos. Pode ser usado em jogos de time onde cada jogador possui um papel. A seleção das classes dentro do jogo pode ser feita com o uso de um dispositivo Class Selector.

Em nosso projeto vamos usar apenas um dispositivo Class Designer para definir a arma inicial do jogador e seu escudo. Modificaremos o Island Setting para indicar que o jogador usará esta nova classe. 

Acesse o Content Drawer e a pasta Fortnite > Devices. Pesquise por class 



Arraste o Class Designer e solte-o no nível perto dos dispositivos Round Settings. Na aba Details, você pode mudar o nome e descrição da classe.  Em Class Identifier coloque Class Slot 1:


No array Item List você adiciona os items que o jogador irá receber quando for desta classe. Em nosso jogo vamos dar apenas uma pistola. 

Clique no botão + na linha do Item List para adicionar um elemento no array.  Clique na pequena seta ao lado de Index [ 0 ] para acessar as propriedades do item. Clique no drop-down de Item Definition e selecione uma das pistolas disponíveis. 


Nesta classe o jogador receberá o escudo cheio. Marque a opção Starting Shield Percentage e coloque o valor 100:


O próximo passo é atualizar o Island Settings para que o jogador utilize a nova classe que criamos com o Class Designer.

Acesse a aba Outliner e selecione o IslandSettings0. Na aba Details, categoria User Options - Game Rules, mude o Default Class Identifier para Class Slot 1:



Salve o nível e inicie a sessão. Observe ao iniciar a partida que o jogador já terá uma pistola e o seu escudo estará cheio.

No próximo artigo vamos usar dispositivos Guard Spawners para criar desafios para o jogador.


Sumário Verse


quarta-feira, 25 de outubro de 2023

UEFN Verse: 2nd version of round_based_device

In this article we will modify the round_based_device Verse code to configure each round in a different way.

Click the Verse button on the UEFN toolbar to open Visual Studio Code.

Add two integer variables named NumberOfAreasCaptured and CurrentRound. Initialize these variables with the value 0. These two variables do not have the @editable attribute because they will only be used in the Verse code.

Let's create constants to reference each of the Round Settings devices that are in the level. The round_based_device variables and constants will look like this:

round_based_device := class(creative_device):

    @editable
    EndGameDevice : end_game_device = end_game_device{}

    @editable 
    CaptureAreas: []capture_area_device = array{}

    var NumberOfAreasCaptured : int = 0

    var CurrentRound : int = 0

    @editable
    Round1Device : round_settings_device = round_settings_device{}

    @editable
    Round2Device : round_settings_device = round_settings_device{}

    @editable
    Round3Device : round_settings_device = round_settings_device{}

    @editable
    Round4Device : round_settings_device = round_settings_device{}

    @editable
    Round5Device : round_settings_device = round_settings_device{}


The Round Settings device has an event called RoundBeginEvent. Only the Round Settings device that is active in the current round will trigger this event at the start of the round.

Let's create a function for each of the Round Settings devices with the name pattern Round1Setup, Round2Setup... These functions are subscribed in the event in the OnBegin function, which should look like this:

    OnBegin<override>()<suspends>:void=
        Round1Device.RoundBeginEvent.Subscribe(Round1Setup)
        Round2Device.RoundBeginEvent.Subscribe(Round2Setup)
        Round3Device.RoundBeginEvent.Subscribe(Round3Setup)
        Round4Device.RoundBeginEvent.Subscribe(Round4Setup)
        Round5Device.RoundBeginEvent.Subscribe(Round5Setup)


The AreaCaptured function needs to be modified. This function is executed when the player captures an area. In this new version, the round will only end when the number of areas captured is equal to the number of the current round. For example, in the third round the player needs to capture 3 areas. 

    AreaCaptured(Agent:agent):void=
        set NumberOfAreasCaptured += 1

        if( NumberOfAreasCaptured = CurrentRound):
            EndGameDevice.Activate(Agent)


Create a function named EnableCaptureAreas. This function receives as a parameter the number of Capture Areas that must be enabled. The function enables the areas and subscribes the AreaCaptured function in the AreaIsScoredEvent event. 

   EnableCaptureAreas(NumberOfAreas:int):void=        
        MaxIndex := NumberOfAreas - 1

        for (Index := 0..MaxIndex):
            if(Area := CaptureAreas[Index]):
                Area.Enable()
                Area.AreaIsScoredEvent.Subscribe(AreaCaptured)

The expression 0..MaxIndex in the for loop is of Range type which represents a series of integers. For example, if MaxIndex has the value 3 then the generated series will be 0, 1, 2 and 3. The for loop will iterate using each of these values which will be stored in the Index constant during the current iteration.

The Index is used in the CaptureAreas array to get the reference of one of the level's Capture Areas. The first element of an array has index 0.

The next step is to create setup functions for each of the rounds. It is in these functions that you will make the specific settings for each round. Create the functions below at the end of the round_based_device file.

    Round1Setup():void=
        set CurrentRound = 1
        
        EnableCaptureAreas(CurrentRound)
                            
    Round2Setup():void=
        set CurrentRound = 2
        
        EnableCaptureAreas(CurrentRound)

    Round3Setup():void=
        set CurrentRound = 3
        
        EnableCaptureAreas(CurrentRound)
             
    Round4Setup():void=
        set CurrentRound = 4
        
        EnableCaptureAreas(CurrentRound)

    Round5Setup():void=
        set CurrentRound = 5
        
        EnableCaptureAreas(CurrentRound)


In this example project, the difference between the rounds is simple, as it only changes the number of enabled areas. In your projects you can define many things in these round setup functions. You can add different devices to the level and make them inactive and invisible. In a specific round you can activate and move them to the game area.

Another option is to create a large island with several different scenarios for each of the rounds. In the round setup you can teleport the player to one of the scenarios.

The Verse code for the 2nd version of round_based_device looks like this:

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

round_based_device := class(creative_device):

    @editable
    EndGameDevice : end_game_device = end_game_device{}

    @editable 
    CaptureAreas: []capture_area_device = array{}

    var NumberOfAreasCaptured : int = 0

    var CurrentRound : int = 0

    @editable
    Round1Device : round_settings_device = round_settings_device{}

    @editable
    Round2Device : round_settings_device = round_settings_device{}

    @editable
    Round3Device : round_settings_device = round_settings_device{}

    @editable
    Round4Device : round_settings_device = round_settings_device{}

    @editable
    Round5Device : round_settings_device = round_settings_device{}

    OnBegin<override>()<suspends>:void=
        Round1Device.RoundBeginEvent.Subscribe(Round1Setup)
        Round2Device.RoundBeginEvent.Subscribe(Round2Setup)
        Round3Device.RoundBeginEvent.Subscribe(Round3Setup)
        Round4Device.RoundBeginEvent.Subscribe(Round4Setup)
        Round5Device.RoundBeginEvent.Subscribe(Round5Setup)

    AreaCaptured(Agent:agent):void=
        set NumberOfAreasCaptured += 1

        if( NumberOfAreasCaptured = CurrentRound):
            EndGameDevice.Activate(Agent)

    EnableCaptureAreas(NumberOfAreas:int):void=        
        MaxIndex := NumberOfAreas - 1

        for (Index := 0..MaxIndex):
            if(Area := CaptureAreas[Index]):
                Area.Enable()
                Area.AreaIsScoredEvent.Subscribe(AreaCaptured)

    Round1Setup():void=
        set CurrentRound = 1
        
        EnableCaptureAreas(CurrentRound)
                            
    Round2Setup():void=
        set CurrentRound = 2
        
        EnableCaptureAreas(CurrentRound)

    Round3Setup():void=
        set CurrentRound = 3
        
        EnableCaptureAreas(CurrentRound)
             
    Round4Setup():void=
        set CurrentRound = 4
        
        EnableCaptureAreas(CurrentRound)

    Round5Setup():void=
        set CurrentRound = 5
        
        EnableCaptureAreas(CurrentRound)


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

Select the round_based_device in the level. In the Details tab, select the references of the 5 Round Settings devices:



We need to disable all Capture Areas in the level. In the Outliner tab, select the 5 Capture Areas:


The Details tab displays the common properties of the selected objects. Any changes will affect all selected objects. Search for enable and change the value of Enable During Phase to None:



Save the level and start the session. Note that the number of Capture Areas enabled is equivalent to the current round. The round will only end when the player captures all enabled areas.


In the next article we will use the Class Designer device to define the player's starting equipment.


Table of Contents Verse