Cannot connect function with effects to event subscription

I’ve been trying to connect a function with and to an event but it doesn’t seem possible at the moment. Would be nice if you could connect any type of function instead. Expected behavior: A player can press a button to carry a prop around above their head.

The line that causes an error:

StartButton.InteractedWithEvent.Subscribe(OnButtonInteractedWith)

“message”: “This function parameter expects a value of type player->void, but this argument is an incompatible value of type type{_(:player):void}.”


using { /Fortnite.com/Devices }
using { /Verse.org/Native }
using { /Verse.org/Simulation }
using { /EpicGames.com/Temporary/Diagnostics }
using { /EpicGames.com/Temporary/SpatialMath }
using { /Fortnite.com/Characters }

# Move the prop to the specified position and rotation over the specified time. Note that if there is an animation currently playing will be stopped and put into an AnimationNotSet state.
# (Prop:creative_prop).MoveTo<public>(Position:vector3, Rotation:rotation, OverTime:float)<suspends>:move_to_result = external {}


log_physic_test_1 := class(log_channel){}

# A Verse-authored creative device that can be placed in a level
# 
# Getting started:
#     https://www.epicgames.com/fortnite/en-US/creative/docs/uefn/Verse/onboarding-guide-to-programming-with-verse-in-unreal-editor-for-fortnite
#
physic_test_1 := class(creative_device):
    Logger:log = log{Channel:=log_physic_test_1}

	@editable
	StartButton:button_device = button_device{}

	@editable
	CarryProp: creative_prop_asset := DefaultCreativePropAsset

	WaitTime: float := 0.01
	Speed: float := 1.0
	ZOffset: float := 10.0

    # Runs when the device is started in a running game
	OnBegin<override>()<suspends>:void=
		StartButton.InteractedWithEvent.Subscribe(OnButtonInteractedWith)

	GetPlayerPosition(Player:player)<transacts><decides>:vector3=
		var c:fort_character := Player.GetFortCharacter[]
		var t:transform := c.GetTransform()
		t.Translation

	Update(Player:player, prop:creative_prop)<suspends><decides>:void=
		loop:
			Sleep(WaitTime)
			var targetPos:vector3 := GetPlayerPosition[Player]
			set targetPos.Z += ZOffset
			
			#prop.MoveTo(currentPos, prop.rotation, 1.0)
			prop.TeleportTo[targetPos, IdentityRotation()]

	OnButtonInteractedWith(Player:player)<suspends><decides>:void=
		var startPos:vector3 := GetPlayerPosition[Player]
		set startPos.Z += ZOffset

		SpawnedProp := SpawnProp(CarryProp, startPos, IdentityRotation())

		if (CreativeProp := SpawnedProp(0)?):
			Update[Player, CreativeProp]

Thank you so much for the feedback, I’ll get this in front of the devs.

Hey @MilesJetMash !

So the problem is that subscriptions don’t support the suspends effect. Normally if you want to trigger a suspends function you need to trigger a normal (:player):void function to then call spawn on your suspends function.

But in your case you don’t need the suspends effect on your handler. You can just remove that and you’ll be fine. suspends is intended for asynchronous operations that need to “wait” for execution at any point in the function. And the current intent of your function should be fine without that.

Hello, I have been adapting the code above, I am trying to use it just to get the players location.

I got this far but get an error saying “This invocation calls a function that has the ‘decides’ effect, which is not allowed by its context.(3512)”

using { /Fortnite.com/Devices }
using { /Verse.org/Native }
using { /Verse.org/Simulation }
using { /EpicGames.com/Temporary/Diagnostics }
using { /EpicGames.com/Temporary/SpatialMath }
using { /Fortnite.com/Characters }

log_testing_vectors := class(log_channel){}

testing_vectors := class(creative_device):
    Logger:log = log{Channel:=log_testing_vectors}

    @editable
	TheButton:button_device = button_device{}

    # Runs when the device is started in a running game
    OnBegin<override>()<suspends>:void=
        Logger.Print("=OnBegin function started=")

        TheButton.InteractedWithEvent.Subscribe(GetPlayerPosition)

    GetPlayerPosition(Player:player):void=
        Logger.Print("=GetPlayerPosition function started=")

        var c : fort_character := Player.GetFortCharacter[]
        var t : transform := c.GetTransform()
        t.Translation

        Logger.Print("Translation = {t.Translation}")
        Print("Translation = {t.Translation}")

When I add the decides effect to GetPlayerLocation I get the following error:
Script error 3509: This function parameter expects a value of type player->void, but this argument is an incompatible value of type type{_(:player):void}.

Could anyone help me fix this snippet so that when a player presses a button it returns the players location please :slight_smile:

@KyleDev Since GetFortCharacter can fail you need to wrap it in an if statement. You could write it like this:

using { /Fortnite.com/Devices }
using { /Fortnite.com/Characters }
using { /Verse.org/Native }
using { /Verse.org/Simulation }
using { /EpicGames.com/Temporary/SpatialMath }
using { /EpicGames.com/Temporary/Diagnostics }

log_player_position_device := class(log_channel){}

player_position_device := class(creative_device):
    Logger:log = log{Channel:=log_player_position_device}

    @editable
    Button : button_device = button_device{}

    # Runs when the device is started in a running game
    OnBegin<override>()<suspends>:void=
       Button.InteractedWithEvent.Subscribe(HandleButtonPressed)

    HandleButtonPressed(Player:player):void=
         if (CharacterTransform:transform := Player.GetFortCharacter[].GetTransform()):
            Logger.Print("Translation = {CharacterTransform.Translation}")
1 Like