How do I check if a volume device is occupied in an if statement

For my level, I have a set of 4 volumes and an NPC Spawner corresponding to each one. What should be happening is while you’re in the volume NPCs will spawn from that corresponding spawner, but when you leave it will disable it. Instead, NPCs spawn out of only 1 spawner regardless of which volume you’re in. The easiest solution is to break these into 4 separate classes but for my sanity I’d rather not, I know I can do this without verse but I’m using verse as I’m adding a mechanic later on. Below is my script showing my issue.

Heres my Code:

using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
SpawnManager := class(creative_device):
    # Volume Devices
    @editable
    VolumeN:volume_device = volume_device{}
    @editable
    VolumeE:volume_device = volume_device{}
    @editable
    VolumeS:volume_device = volume_device{}
    @editable
    VolumeW:volume_device = volume_device{}

    @editable
    NPCSpawnerN:npc_spawner_device = npc_spawner_device{}
    @editable
    NPCSpawnerE:npc_spawner_device = npc_spawner_device{}
    @editable
    NPCSpawnerS:npc_spawner_device = npc_spawner_device{}
    @editable
    NPCSpawnerW:npc_spawner_device = npc_spawner_device{}

    @editable
    MySwitchDevice:switch_device = switch_device{}

    # Runs when the device is started in a running game
    OnBegin<override>()<suspends>:void=
        VolumeN.AgentEntersEvent.Subscribe(OnAgentEntered)
        VolumeE.AgentEntersEvent.Subscribe(OnAgentEntered)
        VolumeS.AgentEntersEvent.Subscribe(OnAgentEntered)
        VolumeW.AgentEntersEvent.Subscribe(OnAgentEntered)
            
        VolumeN.AgentExitsEvent.Subscribe(OnAgentExit)
        VolumeE.AgentExitsEvent.Subscribe(OnAgentExit)
        VolumeS.AgentExitsEvent.Subscribe(OnAgentExit)
        VolumeW.AgentExitsEvent.Subscribe(OnAgentExit)
    OnAgentEntered(Agent:agent):void=
        if (MySwitchDevice.GetCurrentState[] and VolumeN.AgentEntersEvent):
            NPCSpawnerN.Enable()
        else if (MySwitchDevice.GetCurrentState[] and VolumeE.AgentEntersEvent):
            NPCSpawnerE.Enable()
        else if (MySwitchDevice.GetCurrentState[] and VolumeS.AgentEntersEvent):
            NPCSpawnerS.Enable()
        else if (MySwitchDevice.GetCurrentState[] and VolumeW.AgentEntersEvent):
            NPCSpawnerW.Enable()
    OnAgentExit(Agent:agent):void=
        if (MySwitchDevice.GetCurrentState[] and VolumeN.AgentExitsEvent):
            NPCSpawnerN.Disable()
        else if (MySwitchDevice.GetCurrentState[] and VolumeE.AgentExitsEvent):
            NPCSpawnerE.Disable()
        else if (MySwitchDevice.GetCurrentState[] and VolumeS.AgentExitsEvent):
            NPCSpawnerS.Disable()
        else if (MySwitchDevice.GetCurrentState[] and VolumeW.AgentExitsEvent):
            NPCSpawnerW.Disable()`Preformatted text`
1 Like

Hello BizChugg! Welcome to the UEFN forums :innocent:
Sounds like you are building a cool way of controlling the NPC spawners!
As you mentioned, breaking this into 4 separate class instances is better, so lets do that (for your sanity!)

Solution

What is the problem? You want to enable a NPC spawner when there is atleast one player inside the zone. I’m assuming you want this to work for multiple players, since you didn’t specify.

volume_controlled_npc_spawner := class(creative_device):

    @editable
    Volume : volume_device = volume_device{}

    @editable
    NPCSpawner : npc_spawner_device = npc_spawner_device{}

    var InZone : int = 0

    OnBegin<override>():void=
        Volume.AgentEntersEvent.Subscribe(OnEnter)
        Volume.AgentExitsEvent.Subscribe(OnExit)

    OnEnter(Agent:agent):void=
        # Enable the spawner when there was no players, but the event was fired
        if (InZone = 0):
            NPCSpawner.Enable()

        set InZone += 1


    OnExit(Agent:agent):void=
        set InZone -= 1

        # Disable the spawner when there are no players left in the zone
        if (InZone = 0):
            NPCSpawner.Disable()

This will only enable the spawner device when there is atleast 1 player inside the given volume.

I don’t know what the intention of the switch device you were using, but you can certainly implement that into the snippet I gave you here.

:bangbang: NOTE: This code is untested, so I’m not 100% sure if it works.

Personal tips based on your code snipped

1. OnBegin overriding

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=

2. Event Usage

When you have an event, such as Volume.AgentEntersEvent, you can run code in two main ways when the event happens.

First way of handling events

You can “wait” for that event to happen. This means that somewhere in your code, you have to literally freeze the code until that event happens. Commonly, this is used in loops, races or other concurrency contexts.

You can accomplish this by using the .Await() method as such:

loop:
    Volume.AgentEntersEvent.Await() # This will freeze the code, and wait for the event to occur. 
    SomeCodeRunsHereEveryTimeAgentEntersVolume()

:tiger: A slight more advanced usage:
This is particularly useful for when you want to determine which event was triggered when listening to a collection of events. For example, like this:

OnBegin<override>():void=
    for (VolumeIDX->VolumeDevice : VolumeDevices):
         spawn {ListenForVolumeEnter(VolumeDevice, VolumeIDX)}

ListenForVolumeEnter(Volume:volume_device, VolumeIndex:int)<suspends>:void=
    loop:
        Volume.AgentEntersEvent.Await()
        if (HasPlayerUnlockedLevel(Player, VolumeIndex)):
            RunLevelCode(VolumeIndex)

Second way of handling events

You can Subscribe to events. I see that you have done this successfully, so I’m not going to explain this as detailed.

If you want to take a deeper dive, take a loot at this talk by Conan Reis at Unreal Fest 2023 Verse Concurrency—Time Flow: Everything, Everywhere in UEFN, All at Once | Unreal Fest 2023
especially at 29 minutes

:fire: Good luck with your project and feel free to come back to the forums when you need assistance!