Editable array of devices not storing

Summary

I have a verse file called level_manager, it is just a standard creative device. I also have an editable array of type item_granter_devices. I added the item granters in UEFN to the device however they don’t seem to be storing. Anytime I run the .length of that array it always returns 0.

Please select what you are reporting on:

Unreal Editor for Fortnite

What Type of Bug are you experiencing?

Verse

Steps to Reproduce

  1. Create a new verse file
  2. Create an editable array of type item_granter_devices
  3. Get the length of that array

Expected Result

I am expecting to get a length of 11 since there are 11 item granters being stored in that array.

Observed Result

The array returns a length of 0.

Platform(s)

PC

Would you be willing to share a copy of the broken code? I haven’t seen something like this happen personally.

#The problem is when I add the item granters to the array in UEFN and run it, the length returns 0
#I'm also calling check level from another class and passing in the Agent 
    @editable
    ItemGranters:[]item_granter_device = array{}

    #@editable 
    #TestGranter:item_granter_device = item_granter_device{}

    
    GiveItem(Agent:agent, Level:int):void = 
        Print("Item Granter Length {ItemGranters.Length}")
        if: 
            Player := player[Agent]
            Granter:=ItemGranters[Level]
        then:
            Granter.GrantItem(Player)
        else:
            Print("Agent was not a player")

    CheckLevel(Agent:agent):void=
        if:
            Player := player[Agent]
            PlayerXP := PlayerStats.GetXP[Player]  #Get players XP
            Print("Check Level was called")
        then:  
            if(PlayerXP < Level1XP)
            then:
                PlayerStats.SetLevel(Player, 0)
                GiveItem(Agent,0)

ive never experienced this also, Did you try printing below the OnBegin() just out of curiosity ?

Yeah I moved it to OnBegin and it seemed to be fine. I had 2 files, both creative_devices, one was Player_Manager and the other was Level_Manager. The item granters were stored in the Level_Manager file. The Player_Manager would track anytime a player spawned and any time a player was eliminated and call the CheckLevel() function in the Level_Manager File. In the Player_Manager file I instantiated it by doing LevelManager: level_manager = level_manager{}. It would do everything fine except actually grant the items. It would even go past the ItemGranter.GrantItems(Player) to the print statement but never actually grant the items. Both when an elimination happened or the player spawned. I’m going to try to move everything to just the one file.

i think paste both full codes here so we can see and someone can help and explain what your doing wrong or you wont know and could do it again in the future

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

# See https://dev.epicgames.com/documentation/en-us/uefn/create-your-own-device-in-verse for how to create a verse device.

# A Verse-authored creative device that can be placed in a level
level_manager := class(creative_device):


    PlayerStats:player_stats_manager = player_stats_manager{}

    
    Level1XP: float = 1.0

    Level2XP: float = 3.0

    Level3XP: float = 7.0

    Level4XP: float = 11.0

    Level5XP: float = 16.0

    Level6XP: float = 20.0
    
    Level7XP: float = 35.0

    Level8XP: float = 50.0
    
    Level9XP: float = 80.0
 
    Level10XP: float = 100.0
    
    @editable
    ItemGranters:[]item_granter_device = array{}

   

    
    GiveItem(Agent:agent, Level:int):void = 
        if: 
            Player := player[Agent]
            Granter:=ItemGranters[Level]
        then:
            Granter.GrantItem(Player)
        else:
            Print("Agent was not a player")

    CheckLevel(Agent:agent):void=
        if:
            Player := player[Agent]
            PlayerXP := PlayerStats.GetXP[Player]  #Get players XP
            Print("Checking Player Level")
        then:  
            if(PlayerXP < Level1XP):
                PlayerStats.SetLevel(Player, 0)
                GiveItem(Player,0)

            if(PlayerXP >= Level1XP and PlayerXP < Level2XP):
                PlayerStats.SetLevel(Player, 1)
                GiveItem(Player,1)

            if(PlayerXP >= Level2XP and PlayerXP < Level3XP):
                PlayerStats.SetLevel(Agent, 2)
                GiveItem(Player,2)

            if(PlayerXP >= Level3XP and PlayerXP < Level4XP):
                PlayerStats.SetLevel(Agent, 3)
                GiveItem(Player,3)

            if(PlayerXP >= Level4XP and PlayerXP < Level5XP):
                PlayerStats.SetLevel(Agent, 4)
                GiveItem(Player,4)

            if(PlayerXP >= Level5XP and PlayerXP < Level6XP):
                PlayerStats.SetLevel(Agent, 5)
                GiveItem(Player,5)

            if(PlayerXP >= Level6XP and PlayerXP < Level7XP):
                PlayerStats.SetLevel(Agent, 6)
                GiveItem(Player,6)

            if(PlayerXP >= Level7XP and PlayerXP < Level8XP):
                PlayerStats.SetLevel(Agent, 7)
                GiveItem(Player,7)

            if(PlayerXP >= Level8XP and PlayerXP < Level9XP):
                PlayerStats.SetLevel(Agent, 8)
                GiveItem(Player,8)

            if(PlayerXP >= Level9XP and PlayerXP < Level10XP):
                PlayerStats.SetLevel(Agent, 9)
                GiveItem(Player,9)

            if(PlayerXP >= Level10XP):
                PlayerStats.SetLevel(Agent, 10)
                GiveItem(Player,10)
        else:
            Print("Unable to check level")
                
            




    OnBegin<override>()<suspends>:void=
        Print("Item Granters Length {ItemGranters.Length}")


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

# See https://dev.epicgames.com/documentation/en-us/uefn/create-your-own-device-in-verse for how to create a verse device.

# A Verse-authored creative device that can be placed in a level
player_manager := class(creative_device):

    PlayerStatsManager:player_stats_manager = player_stats_manager{} #Creates an instance of class so can use methods
    PlayerLevelManager:level_manager = level_manager{}

    #debug
    @editable
    CheckLevelButton:button_device = button_device{}

    @editable
    AddLevelButton:button_device = button_device{}
    #debug

    @editable
    MonsterElimXP:float = 0.3

    @editable
    PlayerElimXP:float = 0.0

    @editable
    MonsterSpawners: []creature_spawner_device = array{}

    @editable
    PlayerSpawnersArray:[]player_spawner_device=array{}

    


    
    Level1XP: float = 1.0

    Level2XP: float = 3.0

    Level3XP: float = 7.0

    Level4XP: float = 11.0

    Level5XP: float = 16.0

    Level6XP: float = 20.0
    
    Level7XP: float = 35.0

    Level8XP: float = 50.0
    
    Level9XP: float = 80.0
 
    Level10XP: float = 100.0
    
   
    

 # Runs when the device is started in a running game
    OnBegin<override>()<suspends>:void=
        # TODO: Replace this with your code
        #Debug
        #CheckLevelButton.InteractedWithEvent.Subscribe(CheckLevel)
        #AddLevelButton.InteractedWithEvent.Subscribe(AddLevel)
        #Debug
        #Print("Lenght of item granters is {ItemGranter.Length}")
        
        for(spawner : PlayerSpawnersArray):
            spawner.SpawnedEvent.Subscribe(PlayerLevelManager.CheckLevel)
            Print("Intialized Spawner")
       

        #Initialize Current Players
        PlayersArray := GetPlayspace().GetPlayers()
        PlayerStatsManager.InitializeAllPlayers(PlayersArray)

        GetPlayspace().PlayerAddedEvent().Subscribe(PlayerStatsManager.InitializePlayer)

        

        #Display all stats (DEBUG)
        for(p:PlayersArray):
            DisplayStats(p)
            PlayerLevelManager.CheckLevel(p)
            Print("Initial Level check and Grant")
            PlayerStatsManager.SetLevel(p,0) #Change this in full
        
        
        
       #Connect all the creature spawners
       for(spawners : MonsterSpawners):
            spawners.EliminatedEvent.Subscribe(OnMonsterElim)
            Print("Creature Spawner connected")
    
   
    OnMonsterElim(Result:device_ai_interaction_result):void = 
        
        if:
            Player := Result.Source?
            CurrentXP := PlayerStatsManager.GetXP[Player]
            
        then:
            Print("Current XP is {CurrentXP}")
            PlayerStatsManager.AddXP(Player,MonsterElimXP)
            Print("Added {MonsterElimXP}")
            PlayerLevelManager.CheckLevel(Player)
            #CheckLevel(Player)  #Anytime XP is added, check level
        else:
            Print("The creature was not killed by a player, or unsuccessful lookup")

    DisplayStats(Player:player):void=
        if:
            pXP := PlayerStatsManager.GetXP[Player]
            pLevel := PlayerStatsManager.GetLevel[Player]
            pWins := PlayerStatsManager.GetWins[Player]
        then:
            Print("XP = {pXP}")
            Print("Level = {pLevel}")
            Print("Wins = {pWins}")

Ok so I understand this code is probably wrong but I think I found the real issue. The item granters are storing now so either it was just something weird at first or I’m not completely sure. The issue I’m having is the PlayerSpawned.Subscribe(PlayerLevelManager.CheckLevel()) because it passes a tuple instead of just the agent like I thought it did. So I think the granters aren’t working because that first if statement in CheckLevel() fails. Would it be easier to just put this all in one file and what is the proper way of actually using the PlayerSpawned event. I thought it just passed the Agent it spawned.