Attribute Evaluator not working when attempting to find player's class

I have a verse device that contains both a single button and an array of 4 Attribute evaluators. The InitEvaluators subscribes all evaluators’ Pass/Fail events to different functions. The issue I’m having is when I try to run GetClass, the evaluator doesn’t seem to run the correct function when a Pass event is triggered. In the pass event, it should turn on a local variable FoundClass to true, which should then stop the GetClass for loop function from increasing the ThisClass value, which then should return the integer of the class the player is. But everytime I click the button to run the GetClass function, it always outputs a class of 5 when I’m a class 1.

Local variable “var FoundClass : logic = false”
Local variable “@editable var ClassCheckers : []attribute_evaluator_device = array{}”

InitEvaluators():void=
    for(ClassCheck : ClassCheckers):
        ClassCheck.PassEvent.Subscribe(TurnOnClass)
        ClassCheck.FailEvent.Subscribe(TurnOffClass)

TurnOnClass(Agent : agent):void=
    set FoundClass = true

TurnOffClass(Agent : agent):void=
    set FoundClass = false

GetClass(Agent : agent):int=
    var ThisClass : int = 1
    for(ClassCheck : ClassCheckers):
        if(FoundClass = false):
            Print("Current class checking: {ThisClass}")
            ClassCheck.EvaluateAgent(Agent)
            set ThisClass += 1
    Print("Class: {ThisClass}")
    set FoundClass = false
    return ThisClass

The below code should do what you want. It correctly printed the selected class index when I tried it in game.


using { /Fortnite.com/Devices }
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
class_checker_device := class(creative_device):

    @editable 
    ClassCheckers : []attribute_evaluator_device = array{}
    @editable  
    Button : button_device = button_device{}

    # Runs when the device is started in a running game
    OnBegin<override>()<suspends>:void=
        Button.InteractedWithEvent.Subscribe(OnButtonPressed) <# Provides a way for this code to be ran #>

    OnButtonPressed(Agent:agent):void=
        spawn:
            GetPlayersClassIndex(Agent) <# spawn our suspends function #>
    
    GetPlayersClassIndex(Agent:agent)<suspends>:void=
        ClassIndex:int = race: <# This race evaluates all 4 of the following things at the same time, the first one that responds is the winner (and its value is used to set ClassIndex) the others get canceled #>
            EvaluateClass(Agent,0)
            EvaluateClass(Agent,1)
            EvaluateClass(Agent,2)
            EvaluateClass(Agent,3)
        Print("Your Selected Class is {ClassIndex + 1}") <# our array starts at zero, Fortnite's class indexes start at 1 #>

    EvaluateClass(Agent:agent,InCheckerIndex:int)<suspends>:int=
        if(L_ClassChecker:=ClassCheckers[InCheckerIndex]):
            L_ClassChecker.EvaluateAgent(Agent)
            L_ClassChecker.PassEvent.Await()
            return InCheckerIndex
        Sleep(30.0) <# give other threads time to succeed #>
        return -1

1 Like

Just curious, do you need the Sleep(30.0)? It seems to delay everything else by a lot, and I’m using spawn on the function “GetPlayersClassIndex”

Okay so the issue I am having now is that if I click a UI button for the first time, it does not display a class. But when I click the UI button again, the previous message gets printed, as if every UI button click is ‘paused’ and only released on the next click.