Dynamically creating a message in Verse?

I’ve been working on some simple systems and concepts to showcase for work placement, and I’ve been chipping away at a simple system to show sequential text when you interact with a character. I have an editable array of strings which will be ran through. I thought since I’m showcasing different UEFN elements that using a HUD message device accompanied with verse would be the best thing to do as I’ve been doing similar things prior, but I’m a bit stuck. The hud message function SetText takes a message, is there no way to make one dynamically from an entry in the array at runtime?

1 Like

Create a method that takes a value and returns a message:
SetDynamicText<localizes>(IntValue:int) : message = "Dynamic text {IntValue}"

Then pass this into the widget’s SetText:
Widget.SetText(SetDynamicText(0))

1 Like

That method only works with a string literal right? I need it to be able to get a string from an array that can be edited from Unreal Engine.

This doesn’t work unfortunately:

SetDynamicText(IntValue:int) : message = textMessages[IntValue]

Not sure how to do code blocks lol

Try:
SetDynamicText<localizes>(Index:int) : message = "{textMessages[Index]}"

Just to clarify, is SetDynamicText a method to be placed inside the class like other methods? Having some trouble with some errors. I’m a bit new to the syntax in Verse, I’m more used to C++, C# Java etc.

Here’s the entirety of the code in case you can spot something I’m missing:

TalkingNpcDevice := class(ActivatableBase)
{
    @editable
    characterDevice : character_device = character_device{}

    @editable
    hudMessage : hud_message_device = hud_message_device{}

    @editable
    textMessages : []string = array{}

    var timeUntilNextMessage : float = 1.0
    var currentTextIndex : int = -1


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


    SetDynamicText<localizes>(Index:int) : message = "{textMessages[Index]}"

    BeginInteract(relevantAgent:agent):void=
    {
        loop
        {
            set currentTextIndex += 1
            hudMessage.SetText(SetDynamicText(currentTextIndex))
            Sleep(3.0)
        }
    }

}

Yes, its a method, just a one line shortened version. Here is that same method that might make it look more readable:

SetDynamicText<localizes>(Index:int) : message =
{
    return "{textMessages[Index]}"
}

But , what errors are you seeing? I’m guessing it might not like returning the value from the array directly and instead wants a decides? (decides = conditional check for null or index out of range when accessing values from an array) If so, try this version:

SetDynamicText<localizes>(Index:int) : message =
{
    if (ArrayMessage := textMessages[Index])
    {
        return "{ArrayMessage}"
    }
    return "Null Message!"
}

The SetDynamicText method itself gives me two errors:

Localized messages may only be initialized with a string literal.(3638)
Expected definition but found error.(3560)

The SetDynamicText call in BeginInteract gives me the error:

Unknown identifier `SetDynamicText`.

I don’t know how it can be unknown if the method is defined, maybe the error in SetDynamicText is causing the second error to appear.

Umm yeah not sure, but one thing I did notice is that your callback method has a loop and a sleep call. That requires the method to be a suspends method and the callback from the character device can’t be a suspends method. So you will need a separate method to handle that. Like this:

BeginInteract(relevantAgent:agent):void=
{
    spawn { UpdateMessage() } 
}

UpdateMessage()<suspends>:void=
{
    loop
    {
        set currentTextIndex += 1
        hudMessage.SetText(SetDynamicText(currentTextIndex))
        Sleep(3.0)
    }
}

Thanks for the help with that one, I was a bit stumped on why Sleep wasn’t working. The various effects are another thing that have confused me in the past.

It’s a shame about the dynamic text though, I’m really not sure why it couldn’t be working, what I sent was the entire class so there’s nothing there that isn’t visible as far as I know.

Okay, I’ve made some progress!

SetDynamicText<localizes>(value:string) : message="{value}"

This works fine, and the only error I have now is to do with a “decides” effect, which I’ve had trouble with in the past with arrays.

The code:

hudMessage.SetText(SetDynamicText(textMessages[currentTextIndex]))

Gives the error:

This invocation calls a function that has the 'decides' effect, which is not allowed by its context.(3512)

Then this should work now:

if (ArrayMessage := textMessages[currentTextIndex])
{
    hudMessage.SetText(SetDynamicText(ArrayMessage))
}
2 Likes

Thank you!

If it’s not too much trouble, could you tell me why that works? I looked at the docs but there didn’t seem to be much on effects.

I’ve edited my title and marked an answer to hopefully make it easier for people to find a similar solution. I don’t know why yours didn’t work, I’ve tried it before in the past.

The decides is equivalate to checking for null or index out of range in C#. And it returns the value into ArrayMessage if it passes those checks. So in C# to do the same you would have something like this:

if (currentTextIndex >= 0 && currentTextIndex < textMessages.Length && textMessages[currentTextIndex] != null)
{
    string ArrayMessage = textMessages[currentTextIndex]
}
2 Likes

Oh that’s actually quite a helpful feature then. Thank you for all the help!

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.