Need Help Making Health Modifier Work for All Players in Verse

Hey, I have a problem with a Verse code I’m using. It’s a Health Modifier code that allows players to modify their own health and shield values. The issue is that this code only targets individual players, meaning only one player can modify their health independently. What I want is for the code to apply to all players at the same time, so when one player modifies their health, all players’ health gets modified simultaneously. Can anyone help me adjust the code to make this work?

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

health_modifier_device := class(creative_device):

@editable
IncreaseHealthTrigger : trigger_device = trigger_device{}

@editable
DecreaseHealthTrigger : trigger_device = trigger_device{}

@editable
IncreaseShieldTrigger : trigger_device = trigger_device{}

@editable
DecreaseShieldTrigger : trigger_device = trigger_device{}

# Runs when the device is started in a running game
OnBegin<override>()<suspends>:void=
    # TODO: Replace this with your code
    IncreaseHealthTrigger.Enable()
    DecreaseHealthTrigger.Enable()
    IncreaseShieldTrigger.Enable()
    DecreaseHealthTrigger.Enable()
    IncreaseHealthTrigger.TriggeredEvent.Subscribe(IncreasePlayerHealth)
    DecreaseHealthTrigger.TriggeredEvent.Subscribe(DecreasePlayerHealth)
    IncreaseShieldTrigger.TriggeredEvent.Subscribe(IncreasePlayerShield)
    DecreaseShieldTrigger.TriggeredEvent.Subscribe(DecreasePlayerShield)


# HEALTH     

# Function to increase Health by 10
IncreasePlayerHealth(Agent : ?agent): void =
    var players: []player = Self.GetPlayspace().GetPlayers()
    if(CurrentPlayer := players[0]):
        if(PlayerCharacter : fort_character = CurrentPlayer.GetFortCharacter[]):
            PlayerCharacter.SetHealth(PlayerCharacter.GetHealth() + 10.0) # Enter amount to increase Health
            Print("Health increased")     


# Function to decrease Health by 10
DecreasePlayerHealth(Agent : ?agent): void =
    var players: []player = Self.GetPlayspace().GetPlayers()
    if(CurrentPlayer := players[0]):
        if(PlayerCharacter : fort_character = CurrentPlayer.GetFortCharacter[]):
            PlayerCharacter.SetHealth(PlayerCharacter.GetHealth() - 10.0) # Enter amount to decrease Health
            Print("Health decreased")

# SHIELD     

# Function to increase Shield by 10
IncreasePlayerShield(Agent : ?agent): void =
    var players: []player = Self.GetPlayspace().GetPlayers()
    if(CurrentPlayer := players[0]):
        if(PlayerCharacter : fort_character = CurrentPlayer.GetFortCharacter[]):
            PlayerCharacter.SetShield(PlayerCharacter.GetShield() + 10.0) # Enter amount to increase Shield
            Print("Shield increased")     


# Function to decrease Shield by 10
DecreasePlayerShield(Agent : ?agent): void =
    var players: []player = Self.GetPlayspace().GetPlayers()
    if(CurrentPlayer := players[0]):
        if(PlayerCharacter : fort_character = CurrentPlayer.GetFortCharacter[]):
            PlayerCharacter.SetShield(PlayerCharacter.GetShield() - 10.0) # Enter amount to decrease Shield
            Print("Shield decreased")
1 Like

Hi, Vency 7! Welcome to the UEFN forums :slight_smile:

The issue you are facing is happening because you are getting only the first player in the playspaces’ player collection.

players[0] # Will only get the first element in the players list

Instead, we want to loop over the players in the playspace.

To do this, we’ll use a for loop. In our case we will use a filtered for loop, which means our for loop has additional conditions to filter which items we will iterate over. In our case, the only additional condition is to get the players fortnite character.

By implementing this in your code, we get:

@editable
IncreaseHealthTrigger : trigger_device = trigger_device{}

@editable
DecreaseHealthTrigger : trigger_device = trigger_device{}

@editable
IncreaseShieldTrigger : trigger_device = trigger_device{}

@editable
DecreaseShieldTrigger : trigger_device = trigger_device{}

OnBegin<override>():void=
    IncreaseHealthTrigger.Enable()
    DecreaseHealthTrigger.Enable()
    IncreaseShieldTrigger.Enable()
    DecreaseHealthTrigger.Enable()
    IncreaseHealthTrigger.TriggeredEvent.Subscribe(IncreasePlayerHealth)
    DecreaseHealthTrigger.TriggeredEvent.Subscribe(DecreasePlayerHealth)
    IncreaseShieldTrigger.TriggeredEvent.Subscribe(IncreasePlayerShield)
    DecreaseShieldTrigger.TriggeredEvent.Subscribe(DecreasePlayerShield)

# Function to increase Health by 10
IncreasePlayerHealth(Agent:?agent):void=
    for:
        Player : GetPlayspace().GetPlayers()
        FC := Player.GetFortCharacter[]
    do:
        FC.SetHealth(PlayerCharacter.GetHealth() + 10.0)
        Print("Health increased") 

# Function to decrease Health by 10
DecreasePlayerHealth(Agent:?agent):void=
    for:
        Player : GetPlayspace().GetPlayers()
        FC := Player.GetFortCharacter[]
    do:
        FC.SetHealth(PlayerCharacter.GetHealth() - 10.0)
        Print("Health decreased")

# Function to increase Shield by 10
IncreasePlayerShield(Agent:?agent):void=
    for:
        Player : GetPlayspace().GetPlayers()
        FC := Player.GetFortCharacter[]
    do:
        FC.SetShield(PlayerCharacter.GetShield() + 10.0)
        Print("Shield increased")

# Function to decrease Shield by 10
DecreasePlayerShield(Agent:?agent):void=
    for:
        Player : GetPlayspace().GetPlayers()
        FC := Player .GetFortCharacter[]
    do:
        FC.SetShield(PlayerCharacter.GetShield() - 10.0)
        Print("Shield decreased")

Read further if you want to improve the code

However, there is a lot of repetition going on in the code. How about we use a more complex approach?

health_type := enum{Health, Shield}

health_trigger := class<concrete>:
    @editable
    Trigger : trigger_device = trigger_device{}

    @editable
    Amount : float = 10.0

    @editable
    HealthType : health_type = health_type.Health

health_modifier := class(creative_device):

    @editable
    HealthTriggers : []health_trigger = array{}
    
    OnBegin<override>():void=
        for (HealthTrigger : HealthTriggers):
            spawn { ListenForHealthTriggerChange(HealthTrigger) }
    
    ListenForHealthTriggerChange(HealthTrigger:health_trigger)<suspends>:void=
        loop:
            HealthTrigger.Trigger.TriggeredEvent.Await()
            if (HealthTrigger.HealthType = health_type.Health):
                for:
                    Player : GetPlayspace().GetPlayers()
                    FC := Player.GetFortCharacter[]
                do:
                    FC.SetHealth(FC.GetHealth() + HealthTrigger.Amount)
                    Print("Health increased")
            else:
                for:
                    Player : GetPlayspace().GetPlayers()
                    FC := Player.GetFortCharacter[]
                do:
                    FC.SetShield(FC.GetShield() + HealthTrigger.Amount)
                    Print("Shield increased")
    

Look at this! Less code and more flexibility.
You can now set up any amount of health triggers in your editable and assign how much they should give (or take, you set a negative value).

Note: The code is untested, so please test it yourself and fix potential syntax errors

Note about overriding OnBegin

I noticed that you overrode your OnBegin function like
OnBegin<override>()<suspends>:void=

However, you had no suspending code in the function body.
It’s worth noting that when overriding OnBegin from a creative_device the <suspends> specifier is optional!

Think about it. A suspending function CAN/has the possibility to run in one frame, where a non-suspending function can NOT run in multiple frames.

Therefore, you only have to write

OnBegin<override>():void=
1 Like

Thank you very much. I have another question. I’m working on another Verse code, and I’m really struggling with it. It’s again about Health and Shield, but this time with a fixed value, meaning that when triggered, all players get the same health and shield. The problem is that when a player is eliminated and respawns, their health resets to 200 HP. Would it be possible for you to help me adjust my code so that the player retains the health they had selected before elimination, instead of it resetting

@editable
HealthSettings: []health_setting = array{}

@editable
EliminationManager: elimination_manager_device = elimination_manager_device{}

@editable
ResetHealthOnElim: logic = true

var CurrentSettingsPerPlayer: [player]health_setting = map{}

OnBegin<override>()<suspends>:void=
    Sleep(0.0)
    DeviceSetup()

DeviceSetup(): void =
    EliminationManager.EliminationEvent.Subscribe(SetHealthAndShield)
    for (HealthSetting : HealthSettings):
        HealthSetting.Init(Self)

GetAllPlayers(): []player =
    AllPlayers := GetPlayspace().GetPlayers()
    return AllPlayers

SetHealthAndShield(MaybeAgent: ?agent): void =
    if:
        Agent := MaybeAgent?
        Player := player[Agent]
        HealthSetting := CurrentSettingsPerPlayer[Player]
        FortCharacter := Agent.GetFortCharacter[]

    then:
        FortCharacter.SetHealth(HealthSetting.Properties.MaxHealth)
        FortCharacter.SetShield(HealthSetting.Properties.MaxShield)

health_setting := class:

@editable
Trigger: trigger_device = trigger_device{}

@editable
AffectsAllPlayers: logic = true

@editable
Properties: health_setting_properties = health_setting_properties{}

var VerseDevice: health_settings_device = health_settings_device{}

Init(MainDevice: health_settings_device): void =
    set VerseDevice = MainDevice
    Trigger.TriggeredEvent.Subscribe(TriggerTriggered)

TriggerTriggered(MaybeAgent: ?agent): void =
    if (Agent := MaybeAgent?):
        AllPlayers := VerseDevice.GetAllPlayers()
        if (AffectsAllPlayers?):
            for (Player : AllPlayers, FortCharacter := Player.GetFortCharacter[]):
                FortCharacter.AdjustHealthAndShield()
                if {set VerseDevice.CurrentSettingsPerPlayer[Player] = Self}
        else:
            if (Player := player[Agent], FortCharacter := Agent.GetFortCharacter[]):
                FortCharacter.AdjustHealthAndShield()
                if {set VerseDevice.CurrentSettingsPerPlayer[Player] = Self}

(FortCharacter: fort_character).AdjustHealthAndShield(): void =
    FortCharacter.SetMaxHealth(Properties.MaxHealth)
    FortCharacter.SetMaxShield(Properties.MaxShield)
    FortCharacter.SetHealth(Properties.StartingHealth)
    FortCharacter.SetShield(Properties.StartingShield)

health_setting_properties := struct:

@editable
MaxHealth: float = 100.0

@editable
MaxShield: float = 100.0

@editable
StartingHealth: float = 100.0

@editable
StartingShield: float = 100.0