So the following code works to set the text on all of the buttons with my tag just fine so I know the array is full. They also all grant the item but it doesn’t do the cool down.
I know the problem is in my GrantItem() function. The disable call is for a single button device but I want it to run on any button device that is interacted with. They shouldn’t all go on cooldown, just the specific one that was pressed and actually just for that player or agent. I’m not sure how to pass in the button or what to do there. So how would I do that?
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
# using { /Verse.org/Simulation/Text }
# A Verse-authored creative device that can be placed in a level
lucky_loot_device := class(creative_device):
# A button that the player can interact with to grant an item - this is a reference to a button device
@editable
var LuckyButton: button_device = button_device{}
# Empty array of button devices
LuckyButtons: []button_device = array{}
# An item granter that will grant an item to the player when the button is interacted with - this is chosen in the editor
@editable
LuckyGranter: item_granter_device = item_granter_device{}
# The amount of time to wait before the button can be interacted with again
@editable
CoolDownTime: float = 2.0
# The message to show when the player can interact with the button
@editable
StringToShow: string = ""
OnBegin<override>()<suspends>:void=
# Convert the string to a message
messageToShow: message = StringToMessage(StringToShow)
# Find all the buttons in the level that have the snowButton tag
FoundButtons := FindCreativeObjectsWithTag(snowButton{})
# For each button, subscribe to the InteractedWithEvent and set the interaction text
for (Button : FoundButtons, ButtonDevice := button_device[Button]):
ButtonDevice.InteractedWithEvent.Subscribe(GrantItem)
# Set the LuckyButtons to the buttons with the snowButton tag
ButtonDevice.SetInteractionText(messageToShow)
set LuckyButtons = LuckyButtons + array{ButtonDevice}
# Function to convert a string to a 'message'
StringToMessage<localizes>(value:string) : message = "{value}"
GrantItem(Agent:agent):void=
# Grant a random item to the player
LuckyGranter.CycleToRandomItem(Agent)
# Disable the button
# LuckyButtons.Disable()
# Wait for the cooldown time
spawn:
Cooldown()
Cooldown()<suspends>:void=
# Wait for the cooldown time
Sleep(CoolDownTime)
# Enable the button
LuckyButton.Enable()
I think I see what you’re trying to do. Your problem is that you need to access the specific button pressed in the “GrantItem” function you subscribed to, but it’s only giving you an agent that pressed that button?
This is a pattern I’ve been using in my code to achieve something similar, but I’m not sure if it’s the sanctioned best practice.
First you will want to define some kind of handler class above your lucky_loot_device class definition.
What does this do? It gives you a valid function to subscribe to (HandleInteractedEvent), but also allows the class you constructed to hold additional data (MyButton).
Now you just need to call the handler in your code where you’re subscribing to the event. Your subscribe would look something like this (I’m doing this off the top of my head to it might be a little wrong):
Now your button knows to use the HandleInteractedEvent inside ButtonHandler, but you’ve also passed along Button
The last step is to modify GrantItem and Cooldown:
GrantItem(InAgent : agent, InButton : button_device) : void=
# Grant a random item to the player
LuckyGranter.CycleToRandomItem(InAgent)
# Disable the button
InButton.Disable()
# Wait for the cooldown time
spawn{Cooldown(InButton)}
Cooldown(InButton : button_device)<suspends>:void=
# Wait for the cooldown time
Sleep(CoolDownTime)
# Enable the button
InButton.Enable()
This way you’re telling Cooldown to keep track of the button you want to re-enable at some point. Each button would now have its own cooldown and use the same item granter to grant items.
That’s a very interesting approach. I will try it out and let you know. I had a few things wrong with that code (like the empty array of buttons not marked with ‘var’). This is how I corrected it:
# An item granter that will grant an item to the player when the button is interacted with - this is chosen in the editor
@editable
LuckyGranter: item_granter_device = item_granter_device{}
# The amount of time to wait before the button can be interacted with again
@editable
CoolDownTime: float = 2.0
# The message to show when the player can interact with the button
@editable
StringToShow: string = ""
OnBegin<override>()<suspends>:void=
# Convert the string to a message
messageToShow: message = StringToMessage(StringToShow)
# Find all the buttons in the level that have the snowButton tag
FoundButtons := FindCreativeObjectsWithTag(snowButton{})
# For each button, subscribe to the InteractedWithEvent and set the interaction text
for (Button : FoundButtons, ButtonDevice := button_device[Button]):
ButtonDevice.SetInteractionText(messageToShow)
spawn:
HandleButton(ButtonDevice)
# Function to convert a string to a 'message'
StringToMessage<localizes>(value:string) : message = "{value}"
HandleButton(ButtonDevice:button_device)<suspends>:void=
# Loop to handle the button being interacted with - essentially a 'while true' loop
loop:
Agent := ButtonDevice.InteractedWithEvent.Await()
GrantItem(Agent)
# set snowAmount = 1.0
ButtonDevice.Disable()
Cooldown()
ButtonDevice.Enable()
GrantItem(Agent:agent):void=
# Grant a random item to the player
LuckyGranter.CycleToRandomItem(Agent)
Cooldown()<suspends>:void=
# Wait for the cooldown time
Sleep(CoolDownTime)```