Multiple parameters in a for i loop?

Hi, im trying to write some dialogue code using variadic functions, from my understanding in variadic functions you can have infinite parameters and im trying to figure out if there’s a way to check the parameters in pairs of 3 (if i’m wording that correctly) basically I want the game to check all 3 paramaters until theres none left but from what I can tell it only checks the first value which is the text is there any way for it to define all 3 parameters at once?
image
image

EDIT: I realize I should explain my system better so here we go

Im using a module script that runs the entire text function
it uses a variadic function which is as follows:
image

image
from my understanding any parameter after … can be infinite butttt when using an i, for loop to check the paramaters it only recognizes the first param (which is the text)

With tables, there are only 2 Variables you use in a for loop, which are the index and the value, here is sample code showing the following

local t = { -- t is our table
    [123] = "myString"
    -- 123 is our index, or in other words, the key that holdsa value
    -- myString is the value of 123 (our index)
}


for index, value in t do -- index, value is often shortened to just i,v
    print(index, value) -- prints the index, and value
end

There isn’t really a way to have more than 2 variables with a table, as thats basically all a table will contain, but an alternatively simple way to do this would be to just assign the value as a table, and give it the data, for example:

index = {text = "", speed = 1, mood = "Angry", ...} -- idk your system

and when iterating through the table

for index, value in ipairs(stuff) do
   print(value.text, value.speed, value.mood)
end

Variadic functions allow to have multiple arguments, but tables only have 2, which were mentioned earlier.

Thanks for responding! But I realize I shouldve explained my system/problem better
I understand that tables only store 2 values
I have a module script that runs a function, the first 2 variables in the function are the player and then the character (for changing the players gui and checking who the char is)
everything after that is formatted like this “text”, textSpeed, mood
from my understanding this means that you could just do those 3 parameters infinitely so I can make the module script handle multiple boxes of text easily
for i, text,speed,mood uses the parameters from the function
and from my knowledge its the only way to define paramaters from a variadic function
maybe im just dumb but tldr can a for i loop handle multiple parameters at once?


image

The quick answer to your question for using multiple parameters with ipairs is no, you cannot get it to return multiple parameters.

However, there are a couple of ways of solving this I would take depending on how much you’re willing to change the way you’re doing things.

The first way is a bit convoluted and rather error-prone but will allow you to continue using your TalkScript.talk(player, char, ...) syntax.

The first approach would be to iterate over the table by values of 3

Code
local stuff = {"text1", 1, "Happy", "text2", 0.5, "Neutral"}
for i = 1, #stuff, 3 do
    local text, speed, mood = stuff[i], stuff[i + 1], stuff[i + 2]
    print(text)
    print(speed)
    print(mood)
end

The second approach would be to use tables as your multiple parameters instead.

Code
module.talk(player, "character", {"text1", 0.02, "Happy"}, {"text2", 0.02, "Mad"})
-- Your code in TalkScript.talk
local stuff = {...}
for i, triplet in ipairs(stuff) do
    local text, speed, mood = triplet[1], triplet[2], triplet[3]
end

However, I would advise doing it these ways as it’s easy to mess up your inputs. Instead, I believe it would be worthwhile for you in the long-term to put in the extra effort of creating a small function that turns your talk inputs into tables that you could perhaps reuse elsewhere, similar to what @DasKairo suggested.

This is how I would go about doing it

Code
type Mood = "Happy" | "Angry" | "Neutral" -- and whatever else is a possible mood
type TalkInfo = {text: string, speed: number, mood: Mood}
local function TalkInfo(text: string, speed: number, mood: Mood) : TalkInfo
    return {text = text, speed = speed, mood = mood}
end

function TalkScript.talk(player, char, ...: TalkInfo)
    -- all of your other code

    local stuff: {TalkInfo} = {...}
    for i, talkInfo in pairs(stuff) do
        local text, speed, mood = talkInfo.text, talkInfo.speed, talkInfo.mood
        print(text)
        print(speed)
        print(mood)
    end

    -- all of your other code
end

-- Somewhere else
-- You can still use multiple parameters, all of the parameters are instead just tables
module.talk(player, "character", TalkInfo("text1", 1, "Happy"), TalkInfo("text2", 0.5, "Neutral"))

The benefit of doing it this way is that it takes advantage of Luau’s type-checking capabilities to make sure you don’t mess up when typing your code (e.g. if you do TalkInfo(1.5, "text42", "Happy", "text43"), the editor will tell you, “Hey, you gave TalkInfo the wrong arguments!” On the other hand, you might find this approach rather verbose and cumbersome, so if you’re willing to do so for the ease of use, there’s nothing wrong with using the other two approaches.

Warning: Cursed Code Ahead

Open At Your Own Risk...

So, you’re fully intent on using a “normal” for loop to iterate through the table? Then it appears we must create a custom iterator function! If the original poster is reading this, this is outside the scope of your question. Please use one of the other approaches.

-- The following code is actually completely valid in normal Lua as long as you remove the Luau-specific features
-- (remove type annotations, turn string interpolation into a formatted string)
local function npairs(list: {any}, n: number?)
    if n == nil then n = 1 end
    assert(n > 0 and math.floor(n) == n, `Attempt to call npairs with invalid n number {n}`)
    local co = coroutine.create(function()
        for i = 1, #list, n do
            coroutine.yield(i, unpack(list, i, i + n))
        end
        return
    end)
    return function()
        return select(2, coroutine.resume(co))
    end
end

local stuff = {"text1", 1, "Happy", "text2", 0.5, "Neutral", "text3"}

for i, team, speed, mood in npairs(stuff, 3) do
    print(i, team, speed, mood) --> 1 text1 1 Happy, 4 text2 0.5 Neutral, 7 text3 nil nil
end
1 Like

YOO THANK YOU THIS IS INSANELY HELPFUL!!!
This is exactly what I was trying to do your third method works perfectly
Ive been trying to get back into roblox scripting after getting knowledge from other game engines and learning ways to optimize my code has been fun tsym!

1 Like

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