I want to get data directly from persistent_currency_manager instead of Trigger, but I want TRIGGER to remain an option for me to specify. I am currently confused and do not know how to connect them.

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

StatTableModule := module:

@editable



TT_Stats<localizes> : message = "Stats will appear on the table, in the order they're defined."
TT_StatIndexOrdering<localizes> : message = "Determines which one of the stats will be used for ordering on the stat table."

StringToMessage<localizes>(String : string) : message = "{String}"
PlayerToMessage<localizes>(Player : player) : message = "{Player}"

stat_data := class<concrete>:
    @editable
    StatName : string = ""
    @editable
    ColumnWidth : float = 0.0
    @editable
    DigitsToDisplayAfterTheDecimal : int = 0
    @editable
    HeaderTextColor : color = NamedColors.White
    @editable
    ValueTextColor : color = NamedColors.White

    

stat_update_data := class<concrete>:
    @editable
    StatIndex : int = 0
    @editable
    UpdateAmount : float = 0.0
    @editable
    UpdateTrigger : trigger_device = trigger_device{}

    var MaybeStatTableDevice : ?stat_table_device = false

    Init(StatTableDevice : stat_table_device):void=
        set MaybeStatTableDevice = option{ StatTableDevice }
        UpdateTrigger.TriggeredEvent.Subscribe(OnUpdateTriggered)

    OnUpdateTriggered(MaybeAgent : ?agent):void=
        if (Agent := MaybeAgent?, StatTableDevice := MaybeStatTableDevice?) :
            StatTableDevice.OnUpdateTriggered(Agent, Self)

agentt_data := class:
    var StatValues : [string]float = map{}

    var MaybeStatTableCanvas : ?canvas = false

stat_table_device := class(creative_device):

    @editable
    PlayerSpawners : []player_spawner_device = array{}

    @editable {ToolTip := TT_Stats }  
    Stats : []stat_data = array{}

    @editable
    StatUpdates : []stat_update_data = array{}

    @editable{ ToolTip := TT_StatIndexOrdering }
    StatIndexForOrdering : int = 0

    @editable
    StatTableAnchor : vector2 = vector2{ X := 1.0, Y := 0.0 }
    @editable
    StatTableAlignment : vector2 = vector2{ X := 1.0, Y := 0.0 }
    @editable
    StatTableOffsets : vector2 = vector2{ X := -32.0, Y := -128.0 }


    @editable
    ValueRowCount : int = 5

    @editable
    HeaderRowHeight : float = 40.0
    @editable
    ValueRowHeight : float = 40.0

    @editable
    OrderColumnWidth : float = 20.0
    @editable
    PlayerNameColumnWidth : float = 60.0

    @editable
    BGColor : color = NamedColors.Black
   @editable
    BGOpacity : type {_X:float where 0.000000 <= _X, _X <= 1.000000} = 0.35

    @editable
    LineThickness : float = 4.0
    @editable
    LineColor : color = NamedColors.White

    @editable
    OrderColumnValueTextColor : color = NamedColors.White

    @editable
    PlayerNameColumnHeaderTextColor : color = NamedColors.White
    @editable
    PlayerNameColumnValueTextColor : color = NamedColors.White

    var AgentMap : [agent]agentt_data = map{}
    var ValueTextsSlotStartIndex : int = 0
    var StatCount : int = 0

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

       
        UpdateStatTableCanvas()
        set StatCount = Stats.Length

        for (Index -> StatUpdate : StatUpdates) :
           Print("Index: {Index}")
           StatUpdate.Init(Self)

        for (Player : GetPlayspace().GetPlayers()) :
            OnPlayerSpawned(Player)

        for (PlayerSpawner : PlayerSpawners):
            PlayerSpawner.SpawnedEvent.Subscribe(OnPlayerSpawned)

    OnPlayerSpawned(Agent : agent):void =
        Print("OnPlayerSpawned")

       

        if (not AgentMap[Agent], Player := player[Agent], PlayerUI := GetPlayerUI[Player]):
           StatTableCanvas := CreateStatTableCanvas()

           AgentData := agentt_data{}

            for (Stat : Stats):

                 if (set AgentData.StatValues[Stat.StatName] = 0.0):

            set AgentData.MaybeStatTableCanvas = option{ StatTableCanvas }
            if (set AgentMap[Agent] = AgentData):

            PlayerUI.AddWidget(StatTableCanvas)
            UpdateStatTableCanvas()

    OnUpdateTriggered(Agent : agent, StatUpdateData : stat_update_data):void =
        Print("OnUpdateTriggered {StatUpdateData.StatIndex}")

        if (AgentData := AgentMap[Agent], Stat := Stats[StatUpdateData.StatIndex]):
            if (set AgentData.StatValues[Stat.StatName] += StatUpdateData.UpdateAmount):

            UpdateStatTableCanvas()

    UpdateStatTableCanvas():void =
        Print("UpdateStatTableCanvas")
         
        StatNameToOrder := if (String := Stats[StatIndexForOrdering].StatName)
        then String
        else ""

        Players := GetPlayspace().GetPlayers()
        var PlayerStatValues : []float = for (Index -> Player : Players, AgentData := AgentMap[Player],
        StatValue := AgentData.StatValues[StatNameToOrder]):
            StatValue

        var OrderedPlayerIndexes : []int = array{}
        for (I := 1 .. ValueRowCount):
            MaxIndex := FindMaxIndex(PlayerStatValues)
            Print("MaxIndex: {MaxIndex}")

            if (MaxValue := PlayerStatValues[MaxIndex], MaxValue >= 0.0):
                Print("MaxIndex: {MaxIndex}")
                set OrderedPlayerIndexes += array{ MaxIndex }

            if (set PlayerStatValues[MaxIndex] = -1.0) {}

        for (Player : Players,AgentData := AgentMap[Player],StatTableCanvas := AgentData.MaybeStatTableCanvas?,
        StatTableInnerCanvas := canvas[StatTableCanvas.Slots[0].Widget]):

            var CurrentSlotIndex : int = ValueTextsSlotStartIndex
            ColumnCount := StatCount + 2

            for (I := 0 .. ValueRowCount - 1):

                 # (frozenpawn): Fill the messages to display for this row.
                 var Messages : []message = array {}
                 if (OrderedPlayerIndex := OrderedPlayerIndexes[I],OrderedPlayer := Players[OrderedPlayerIndex],
                OrderedAgentData := AgentMap[OrderedPlayer]):
                     set Messages = array {StringToMessage("#{I+1}"),PlayerToMessage(OrderedPlayer)}
                     set Messages += for (Stat : Stats,StatValue := OrderedAgentData.StatValues[Stat.StatName]):

                         StringToMessage("{AbbreviateNumberText(StatValue, Stat.DigitsToDisplayAfterTheDecimal)}")

                for (ColumnIndex := 0 .. ColumnCount - 1,TextBlock := text_block[StatTableInnerCanvas.Slots[CurrentSlotIndex].Widget]):
                    MessageToSet := if (Msg := Messages[ColumnIndex])
                    then Msg
                    else StringToMessage("")

                    TextBlock.SetText(MessageToSet)
                    set CurrentSlotIndex += 1

    CreateStatTableCanvas():canvas=
        return canvas:
            Slots := array:
                canvas_slot:
                    Anchors := anchors { Minimum := StatTableAnchor, Maximum := StatTableAnchor }
                    Offsets := margin { Top := StatTableOffsets.Y, Left := StatTableOffsets.X, Right := 0.0, Bottom := 0.0 }
                    Alignment := StatTableAlignment
                    SizeToContent := true
                    ZOrder := 0
                    Widget := CreateStatTableCanvasInner()

    CreateStatTableCanvasInner():canvas=
            BGHeight := HeaderRowHeight + ValueRowCount*ValueRowHeight

            var BGWidth : float = OrderColumnWidth + PlayerNameColumnWidth
            for (Stat : Stats):
                  set BGWidth += Stat.ColumnWidth

            var CanvasSlots : []canvas_slot = array 
            {
                CanvasSlot0 := canvas_slot:
                    Anchors := anchors{ Minimum := vector2{X := 0.0, Y := 0.0}, Maximum := vector2{X := 0.0, Y := 0.0} }
                    Offsets := margin{ Top := 0.0, Left := 0.0, Right := 0.0, Bottom := 0.0 }
                    Alignment := vector2{X := 0.0, Y := 0.0}
                    ZOrder := 0
                    Widget := color_block{ DefaultColor := BGColor, DefaultOpacity := BGOpacity, DefaultDesiredSize := vector2{X := BGWidth, Y := BGHeight} }
            }

            # (frozenpawn): Horizontal Line.
            HorizontalLineLength := BGWidth
            set CanvasSlots += array
            {
                CanvasSlot1 := canvas_slot:
                    Anchors := anchors{ Minimum := vector2{X := 0.0, Y := 0.0}, Maximum := vector2{X := 0.0, Y := 0.0} }
                    Offsets := margin{ Top := HeaderRowHeight, Left := 0.0, Right := 0.0, Bottom := 0.0 }
                    Alignment := vector2{X := 0.0, Y := 0.0}
                    ZOrder := 1
                    Widget := color_block{ DefaultColor := LineColor, DefaultDesiredSize := vector2{X := HorizontalLineLength, Y := LineThickness} }
            }

            # (frozenpawn): Vertical Lines.
            var TotalLeftOffset : float = 0.0
            var ColumnWidths : []float = array { OrderColumnWidth, PlayerNameColumnWidth }

            set ColumnWidths += for (Stat : Stats):
                Stat.ColumnWidth

            LineHeight := BGHeight
            for (I := 0 .. StatCount, ColumnWidth := ColumnWidths[I]):
                set TotalLeftOffset += ColumnWidth
                Print("Vertical Line {I}, Offset: {TotalLeftOffset}, Width: {ColumnWidth}")

                set CanvasSlots += array 
                {
                    CanvasSlot2 := canvas_slot:
                        Anchors := anchors{ Minimum := vector2{X := 0.0, Y := 0.0}, Maximum := vector2{X := 0.0, Y := 0.0} }
                        Offsets := margin{ Top := 0.0, Left := TotalLeftOffset, Right := 0.0, Bottom := 0.0 }
                        Alignment := vector2{X := 0.5, Y := 0.0}
                        ZOrder := 1
                        Widget := color_block{ DefaultColor := LineColor, DefaultDesiredSize := vector2{X := LineThickness, Y := LineHeight} }
                }

            # Header Texts
            set TotalLeftOffset = OrderColumnWidth
            var HeaderStrings : []string = array { "Player Name" }
            var HeaderStringColors: []color = array { PlayerNameColumnHeaderTextColor }

            set HeaderStrings += for (Stat : Stats):
                 Stat.StatName
            set HeaderStringColors += for (Stat : Stats): 
                Stat.HeaderTextColor

            for (I := 0 .. StatCount, HeaderString := HeaderStrings[I], HeaderStringColor := HeaderStringColors[I],
            ColumnWidth := ColumnWidths[I+1]):
                LeftOffset := TotalLeftOffset + ColumnWidth * 0.5
                Print("Header String {I}: {HeaderString}, Offset: {LeftOffset}, Width: {ColumnWidth}")
                set CanvasSlots += array 
                {
                    CanvasSlot3 := canvas_slot:
                        Anchors := anchors { Minimum := vector2{X := 0.0, Y := 0.0}, Maximum := vector2{X := 0.0, Y := 0.0} }
                        Offsets := margin { Top := HeaderRowHeight * 0.5, Left := LeftOffset, Right := 0.0, Bottom := 0.0 }
                        Alignment := vector2 { X := 0.5, Y := 0.5 }
                        ZOrder := 1
                        Widget := text_block {DefaultText := StringToMessage(HeaderString), DefaultTextColor := HeaderStringColor}
                }


                set TotalLeftOffset += ColumnWidth



            set ValueTextsSlotStartIndex = CanvasSlots.Length

            # (frozenpawn): Value TextBlocks.
            var ValueStringColors : []color = array{ OrderColumnValueTextColor, PlayerNameColumnValueTextColor }
            set ValueStringColors += for (Stat : Stats):
                Stat.ValueTextColor

            for (I := 0 .. ValueRowCount-1):
                VerticalOffset := HeaderRowHeight * (ValueRowHeight*I) + ValueRowHeight*0.5
                set TotalLeftOffset = 0.0
                for (Index -> ColumnWidth: ColumnWidths,  ValueStringColor := ValueStringColors[Index]):
                    LeftOffset := TotalLeftOffset + ColumnWidth*0.5

                    set CanvasSlots += array
                    {
                        CanvasSlot4 := canvas_slot:
                            Anchors := anchors{ Minimum := vector2{X := 0.0, Y := 0.0}, Maximum := vector2{X := 0.0, Y := 0.0} }
                            Offsets := margin{ Top := VerticalOffset, Left := LeftOffset, Right := 0.0, Bottom := 0.0 }
                            Alignment := vector2{X := 0.5, Y := 0.5}
                            ZOrder := 1
                            Widget := text_block{ DefaultText := StringToMessage(""), DefaultTextColor := ValueStringColor }
                    }

                    set TotalLeftOffset += ColumnWidth

            return canvas:
                Slots := CanvasSlots

FloatToString(Num : float, DigitsAfterTheDecimal : int)<transacts>:string=
    var String : string := "NaN"

    if (NumInt := Int[Num]):
        set String = "{NumInt}"

        if (DigitsAfterTheDecimal  > 0):
            set String += "."

            for (I := 1 .. DigitsAfterTheDecimal):
                Pow10 := Pow(10.0, I*1.0)

                NumIntPow10 := NumInt*Pow10
                NumPow10 := Num*Pow10
                
                if (NumInPow10Int := Int [NumIntPow10], NumPow10Int := Int [NumPow10],
                Diff  := NumPow10Int - NumInPow10Int, Digit  := Mod [Diff, 10]):
                    set String += "{Digit}"
    return String


AbbreviateNumberText<public>(Number : float, DigitsAfterDecimalPoint : int):string=
    var ResultText : string = ToString(Number)

    Abbreviations : []tuple(float,string) = array
    {
        (1000.0, "K"),
        (1000000.0, "M"),
        (1000000000.0, "B"),
       (1000000000000.0, "T"),
       (1000000000000000.0, "Qa"),
       (1000000000000000000.0, "Qi")
    }

    AbbreviationCount : int = Abbreviations.Length-1
    var CurrBackIndex : int = AbbreviationCount
    for(i:=0..AbbreviationCount):

        if(CurrTuple := Abbreviations[CurrBackIndex]):

             if(Abs(Number) >= CurrTuple(0)):
                 RoundedNumber : float = Number / CurrTuple(0)
                 set ResultText = FloatToString(RoundedNumber, DigitsAfterDecimalPoint) + CurrTuple(1)
                 return ResultText
        set CurrBackIndex -= 1

    if(CeiledValue := Ceil[Number]):
         set ResultText = ToString(CeiledValue)

    return ResultText


FindMaxIndex<public>(Arr : []float):int=
    var MaxIndex : int = -1

    if (FirstValue := Arr[0]):
        var MaxValue : float = FirstValue
        set MaxIndex  = 0

        var I : int = 1 
        loop:
            if (Value := Arr[I]):
                if (MaxValue < Value):
                    set MaxValue = Value
                    set MaxIndex = I 
            else:
                break
                
            set I += 1

    return MaxIndex

##########################################################################

using { /Verse.org/Simulation }
using { /Fortnite.com/Devices }

var PlayerCurrencies : weak_map(player, currency_data) = map{}

Persistable class for currencies

currency_data := class:
Coins : int = 0
Rebirths : int = 0
FirstLogin : int = 0
LastLogin : int = 0

persistent_currency_manager := class(creative_device):

@editable
var coinsHUD: hud_message_device = hud_message_device{}

@editable
var rebirthHUD: hud_message_device = hud_message_device{}

# Helper function to convert string to message
StringToMessage<localizes>(InString : string) : message = "{InString}"

getCurrency(Player:player):currency_data=
    if(not Player.IsActive[]):
        return currency_data{}
    else:
        newBlankCurrency:= currency_data{}
        if(currency:= PlayerCurrencies[Player]):
            return currency
        else:
            return newBlankCurrency

     




InitializePlayerDataNonSuspended(Player:player):void =
    spawn{InitializePlayerDataSuspended(Player)}

# Ensure data is initialized for the player
InitializePlayerDataSuspended(Player:player)<suspends>:void =
    Sleep(1.0)
    if (not PlayerCurrencies[Player]):
        #Print("##################Data does not exist for player, creating new#####################")
        if (set PlayerCurrencies[Player] = currency_data{}):
            setFirstLoginTime(Player)
            spawn{saveLastLoginLoop(Player)}
            addCurrency(Player, 500, 0)
            #Print("##########################Created new currency for user##########################")
    else:
        spawn{saveLastLoginLoop(Player)}
        addCurrency(Player, 0, 0)

saveLastLoginLoop(Player:player)<suspends>:void=
    loop:
        Sleep(30.0)
        if(Player.IsActive[]): 
         setLastLoginTime(Player)
        else. break

OnPlayerRemoved(Player:player):void =
    #Print("Player removed, setting las login time")
    setLastLoginTime(Player)

# Helper: Get current time as int
GetCurrentTimeInt():int =
    if (TimeInt := Int[GetSecondsSinceEpoch()]):
        TimeInt
    else:
        0

setFirstLoginTime(Player:player):void=
    if (Data := PlayerCurrencies[Player]):
       if (Data.FirstLogin = 0):
           NewData := currency_data{
               Coins := Data.Coins,
               Rebirths := Data.Rebirths,
               FirstLogin := GetCurrentTimeInt(),
               LastLogin := Data.LastLogin
           }
        if (set PlayerCurrencies[Player] = NewData) {
            #Print("First login time is {NewData.FirstLogin}")
        }

setLastLoginTime(Player:player):void=
   if(Player.IsActive[]):
    if (Data := PlayerCurrencies[Player]):
        NewData := currency_data{
            Coins := Data.Coins,
            Rebirths := Data.Rebirths,
            FirstLogin := Data.FirstLogin,
            LastLogin := GetCurrentTimeInt()
        }
        if (set PlayerCurrencies[Player] = NewData) {
            #Print("Last login time is {NewData.LastLogin}")
        }


# Combined setter for Coins and Rebirths
zeroCoins(Player:player):void=
    if (OldData := PlayerCurrencies[Player]):
        NewData := currency_data{
            Coins := 1000,
            Rebirths := OldData.Rebirths,
            FirstLogin := OldData.FirstLogin,
            LastLogin := OldData.LastLogin
        }
        if (set PlayerCurrencies[Player] = NewData, Agent:= agent[Player]){}

addCurrency(Player:player, NewCoins:int, NewRebirths:int):void =
    if (OldData := PlayerCurrencies[Player]):
        NewData := currency_data{
            Coins := OldData.Coins + NewCoins,
            Rebirths := OldData.Rebirths + NewRebirths,
            FirstLogin := OldData.FirstLogin,
            LastLogin := OldData.LastLogin
        }
        if (set PlayerCurrencies[Player] = NewData, Agent:= agent[Player]) {
            if(currentCoins:= PlayerCurrencies[Player].Coins, currentRebirths:= PlayerCurrencies[Player].Rebirths):
             coinsMessage:= StringToMessage("{suffixAdd(currentCoins)}")
             rebirthMessage:= StringToMessage("{suffixAdd(currentRebirths)}")
             #Print("###################################### New saved coins are {currentCoins}##############################")
             coinsHUD.Show(Agent, coinsMessage)
             rebirthHUD.Show(Agent, rebirthMessage)
        }

# Combined setter for Coins and Rebirths
deductCurrency(Player:player, deductCoins:int, NewRebirths:int):void =
    if (OldData := PlayerCurrencies[Player]):
        NewData := currency_data{
            Coins := OldData.Coins - deductCoins,
            Rebirths := OldData.Rebirths,
            FirstLogin := OldData.FirstLogin,
            LastLogin := OldData.LastLogin
        }
        if (set PlayerCurrencies[Player] = NewData, Agent:= agent[Player]) {
            if(currentCoins:= PlayerCurrencies[Player].Coins):
             coinsMessage:= StringToMessage("{suffixAdd(currentCoins)}")
             #Print("######################################New saved coins are {currentCoins}#############################")
             coinsHUD.Show(Agent, coinsMessage)
        }

suffixAdd(InputNum:int):string=
    Trillion:float = 1000000000000.0
    Billion:float = 1000000000.0
    Million:float = 1000000.0
    Thousand: float = 1000.0
    Hundreads: float = 100.0
    Tens: float = 10.0
    
    
    var InputNumFloat:float = InputNum*1.0 
    var suffix:string=""
    var finalNum:float=0.0
    var length:int = 1

    if(InputNumFloat>= Trillion):
        set suffix = "T"
        set finalNum = InputNumFloat/Trillion
        set length= 4

    else if(InputNumFloat>= Billion):
        set suffix = "B"
        set finalNum = InputNumFloat/Billion
        set length= 4

    else if(InputNumFloat>= Million):
        set suffix = "M"
        set finalNum = InputNumFloat/Million
        set length= 4

    else if(InputNumFloat>= Thousand):
        set suffix = "K"
        set finalNum = InputNumFloat/Thousand
        set length= 4

    else if(InputNumFloat>= Hundreads):
        set finalNum = InputNumFloat
        set suffix = ""
        set length= 3

    else if(InputNumFloat>= Tens):
        set finalNum = InputNumFloat
        set suffix = ""
        set length= 2

    else:
        set finalNum = InputNumFloat
        set suffix = ""
        set length= 1
        
        
    return SplitString(ToString(finalNum), suffix, length)


SplitString(InputString:string, Suffix:string, length:int) : string =
 StringLength := InputString.Length
 var returnString:string = "Failed"

    if:
        tempString:=InputString.Slice[0, length] + ToString(Suffix)
        set returnString = tempString
        
    return returnString


# Handle new player joining
OnPlayerAdded(Player:player):void =
    Print("@@@@@@@@@@@@@@@@@@@@@Currencyyyyyyyy@@@@@@@@@@@@@@@@@@@@@@@@@")
    InitializePlayerDataNonSuspended(Player)
    
    
OnBegin<override>()<suspends>:void =
    # Subscribe to new player joins
    GetPlayspace().PlayerAddedEvent().Subscribe(OnPlayerAdded)
    GetPlayspace().PlayerRemovedEvent().Subscribe(OnPlayerRemoved)

    Players := GetPlayspace().GetPlayers()
    for (Player : Players):
        InitializePlayerDataNonSuspended(Player)

I want to get data directly from persistent_currency_manager instead of Trigger, but I want TRIGGER to remain an option for me to specify. I am currently confused and do not know how to connect them.