Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
0

Wait acting as if it's not there. Any help?

Asked by 6 years ago
Edited 6 years ago

What I planned for this script to do is run the flag function when a value is changed. In the flag function, the value number has 1 added or subtracted depending on different circumstances. If the value number has not reached the point clarified in the script, it should wait one second and run the function again. Every part of this works other than the wait part. It seems as if there is no wait between the running of flag. Nothing appears in the output and from what I know of scripting (even if I don't know much) this should work.

number = 0
function update()
    if number == -13 then
        script.Parent.flag.CFrame = CFrame.new(126.961, 390.416, -419.518)
    elseif number == -12 then
        script.Parent.flag.CFrame = CFrame.new(126.961, 389.416, -419.518)
    elseif number == -11 then
        script.Parent.flag.CFrame = CFrame.new(126.961, 388.416, -419.518)
    elseif number == -10 then
        script.Parent.flag.CFrame = CFrame.new(126.961, 387.416, -419.518)
    elseif number == -9 then
        script.Parent.flag.CFrame = CFrame.new(126.961, 386.416, -419.518)
    elseif number == -8 then
        script.Parent.flag.CFrame = CFrame.new(126.961, 385.416, -419.518)
    elseif number == -7 then
        script.Parent.flag.CFrame = CFrame.new(126.961, 384.416, -419.518)
    elseif number == -6 then
        script.Parent.flag.CFrame = CFrame.new(126.961, 383.416, -419.518)
    elseif number == -5 then
        script.Parent.flag.CFrame = CFrame.new(126.961, 382.416, -419.518)
    elseif number == -4 then
        script.Parent.flag.CFrame = CFrame.new(126.961, 381.416, -419.518)
    elseif number == -3 then
        script.Parent.flag.CFrame = CFrame.new(126.961, 380.416, -419.518)
    elseif number == -2 then
        script.Parent.flag.CFrame = CFrame.new(126.961, 379.416, -419.518)
    elseif number == -1 then
        script.Parent.flag.CFrame = CFrame.new(126.961, 378.416, -419.518)
    elseif number == 0 then
        script.Parent.flag.CFrame = CFrame.new(126.961, 377.416, -419.518)
    elseif number == 1 then
        script.Parent.flag.CFrame = CFrame.new(126.961, 378.416, -419.518)
    elseif number == 2 then
        script.Parent.flag.CFrame = CFrame.new(126.961, 379.416, -419.518)
    elseif number == 3 then
        script.Parent.flag.CFrame = CFrame.new(126.961, 380.416, -419.518)
    elseif number == 4 then
        script.Parent.flag.CFrame = CFrame.new(126.961, 381.416, -419.518)
    elseif number == 5 then
        script.Parent.flag.CFrame = CFrame.new(126.961, 382.416, -419.518)
    elseif number == 6 then
        script.Parent.flag.CFrame = CFrame.new(126.961, 383.416, -419.518)
    elseif number == 7 then
        script.Parent.flag.CFrame = CFrame.new(126.961, 384.416, -419.518)
    elseif number == 8 then
        script.Parent.flag.CFrame = CFrame.new(126.961, 385.416, -419.518)
    elseif number == 9 then
        script.Parent.flag.CFrame = CFrame.new(126.961, 386.416, -419.518)
    elseif number == 10 then
        script.Parent.flag.CFrame = CFrame.new(126.961, 387.416, -419.518)
    elseif number == 11 then
        script.Parent.flag.CFrame = CFrame.new(126.961, 388.416, -419.518)
    elseif number == 12 then
        script.Parent.flag.CFrame = CFrame.new(126.961, 389.416, -419.518)
    elseif number == 13 then
        script.Parent.flag.CFrame = CFrame.new(126.961, 390.416, -419.518)
    end
end
function flag()
    if script.Parent.teamtaking.Value == "R" then
        if number == 0 then
            script.Parent.flag.BrickColor = BrickColor.new("Bright red")
            script.Parent.pole.BillboardGui.tag.BackgroundColor3 = Color3.new(1,0.137254902,0.137254902)
        end
        number = number + 1
        update()
        for _,player in pairs (script.Parent.rplayers:GetChildren()) do
            if player then
                plr = game.Players:GetPlayerFromCharacter(player.Value)
                plr.playerpointstore.Value = plr.playerpointstore.Value + 10
            end
        end
        if number == 13 then
            script.Parent.team.Value = "R"
        else
            wait(1)
            flag()
        end
    elseif script.Parent.teamtaking.Value == "B" and number ~= -13 then
        if number == 0 then
            script.Parent.flag.BrickColor = BrickColor.new("Bright blue")
            script.Parent.pole.BillboardGui.tag.BackgroundColor3 = Color3.new(0.137254902,0.137254902,1)
        end
        number = number - 1
        update()
        for _,player in pairs (script.Parent.bplayers:GetChildren()) do
            if player then
                plr = game.Players:GetPlayerFromCharacter(player.Value)
                plr.playerpointstore.Value = plr.playerpointstore.Value + 10
            end
        end
        if number == -13 then
            script.Parent.team.Value = "B"
        else
            wait(1)
            flag()
        end
    elseif script.Parent.teamtaking.Value == "N" and script.Parent.team.Value == "R" and number ~= 13 then
        script.Parent.team.Value = "R"
        number = number + 1
        update()
        if number ~= 13 then
            wait(1)
            flag()
        end
    elseif script.Parent.teamtaking.Value == "N" and script.Parent.team.Value == "B" and number ~= -13 then
        script.Parent.team.Value = "B"
        number = number - 1
        update()
        if number ~= -13 then
            wait(1)
            flag()
        end
    elseif script.Parent.teamtaking.Value == "N" and script.Parent.team.Value == "N" and number < 0 then
        script.Parent.team.Value = "N"
        number = number + 1
        update()
        if number == 0 then
            script.Parent.flag.BrickColor = BrickColor.new("Institutional white")
            script.Parent.pole.BillboardGui.tag.BackgroundColor3 = Color3.new(1,1,1)
        else
            wait(1)
            flag()
        end
    elseif script.Parent.teamtaking.Value == "N" and script.Parent.team.Value == "N" and number > 0 then
        script.Parent.team.Value = "N"
        number = number - 1
        update()
        if number == 0 then
            script.Parent.flag.BrickColor = BrickColor.new("Institutional white")
            script.Parent.pole.BillboardGui.tag.BackgroundColor3 = Color3.new(1,1,1)
        else
            wait(1)
            flag()
        end
    end
end
script.Parent.teamtaking.Changed:connect(function()
    flag()
end)
1
Did you print debug it to make sure it's the wait and not anything else? Viking359 161 — 6y
0
It seems to be completely fine. There should be a closed parenthesis after the end at the bottom. It doesn't make a difference though. smartlegomaniac 0 — 6y
0
jesus that's so many `elseif`s, you should use a dictionary creeperhunter76 554 — 6y
0
Does anyone think they have an answer to my question? smartlegomaniac 0 — 6y

1 answer

Log in to vote
0
Answered by 6 years ago
Edited 6 years ago

Short answer: You need probably need debounce to protect your flag function from being called multiple times by teamtaking.Changed.

Long answer: I'm going to take you on a journey of improving your script.

First of all, your script can be significantly simplified (which will let us debug it easier). The guideline is that if you ever have a bunch of code that looks similar to each other, you should instead use a loop, function, dictionary, or - in this case - math. In update you have a whole bunch of 'if' statements, with the only difference being a y-coordinate. You can write it like this:

script.Parent.flag.CFrame = CFrame.new(126.961, 377.416 + math.abs(number), -419.518)

math.abs returns the positive value of what's given to it, so math.abs(5) == 5 and math.abs(-5) == 5 also.

Next, you use 13 in many places. You might want to change that number later, so it's good practice to assign it to a variable and use the variable instead. (You might be able to get away with just doing find/replace, but if you happen to have "13" anywhere else in your script for a different purpose, you'll accidentally overwrite stuff that shouldn't be changed.) Let's call this number max.

Another thing I see you doing is updating the number value and then calling update. It's good you have an update function, but you can do better by making it setNumber -- both update the number and the flag:

function setNumber(newNumber)
    number = newNumber
    local absNumber = math.abs(newNumber)
    if absNumber > 13 then return end -- alternatively you could error here if the number should never be < -13 or > 13
    script.Parent.flag.CFrame = CFrame.new(126.961, 377.416 + absNumber, -419.518)
end

--Elsewhere, every instance of
number = number + 1
update()
--is now just:
setNumber(number + 1)

Now, looking at your flag function, you again have lots of duplicate code with only slight differences. When this happens, it's good to use a function -- every difference becomes a new argument.

Specifically, see how lines 61-78 are nearly identical to 80-97? Put those lines into a function where each difference is an argument (ex, the first difference is that they assign different colors, so we need (amongst others) the parameters flagColor and poleColor):

function recordTeamIsCapturing(teamName, flagColor, poleColor, captureDir, modelName)
    -- teamName: "R", "B", etc
    -- captureDir: what to change 'number' by (-1 or 1)
    -- modelName: the name of the model in script.Parent to reward players by (ex "rplayers" or "bplayers")
    if number == 0 then
        script.Parent.flag.BrickColor = flagColor
        script.Parent.pole.BillboardGui.tag.BackgroundColor3 = poleColor
    end
    setNumber(number + captureDir)
    for _, player in ipairs(script.Parent[modelName]:GetChildren()) do
        plr = game.Players:GetPlayerFromCharacter(player.Value)
        if plr then -- Note: I've changed this. "player" will always exist (what you had before), but 'plr' might not (since GetPlayerFromCharacter can return nil). If you wanted to be completely safe you'd also check to make sure that the player has 'playerpointstore' before trying to increase its value.
            plr.playerpointstore.Value = plr.playerpointstore.Value + 10
        end
    end
    if number == max * captureDir then
        script.Parent.team.Value = teamName
    else
        wait(1)
        flag()
    end
end
--Calls to be made in flag:
recordTeamIsCapturing("R", BrickColor.new("Bright red"), Color3.new(1,0.137254902,0.137254902), 1, "rplayers")
recordTeamIsCapturing("B", BrickColor.new("Bright blue"), Color3.new(0.137254902,0.137254902,1), -1, "bplayers")

A lot less code. Most importantly, you only need to change the code in one place if you decide to change it later.

You notice how you have 'script.Parent.teamtaking.Value' everywhere? The script looks a lot better if you save the object to a local variable: local teamtaking = script.Parent.teamtaking (notably, do not say .Value at the end of that line, or else teamtaking won't get updated. To get the value, say teamtaking.Value -- still shorter than what you had). Better, let's use WaitForChild in case of loading order problems:

--At the top of your script:
local teamtaking = script.Parent:WaitForChild("teamtaking")
local team = script.Parent:WaitForChild("team")
local flag = script.Parent:WaitForChild("flag")
local poleTag = script.Parent:WaitForChild("pole").BillboardGui.tag -- you could also wait for BillboardGui and tag here if you wanted

Next I see a lot of elseif statements (repeatedly checking to see if script.Parent.teamtaking.Value == "n"). Instead of repeating yourself over and over, just put them all into a single block:

--in flag, ignoring the code in between the elseifs for a moment:
elseif teamtaking.Value == "N" then
    if team.Value == "R" and number ~= max then
    elseif team.Value == "B" and number ~= -max then
    elseif team.Value == "N" then
        if number < 0 then
        elseif number > 0 then
        end
    end
end

Now, the code in between each of those elseifs is also a duplicate of each other. Instead of putting it into a function, however, note the following:

  • You set team.Value to be whatever you already confirmed it to be. That is, if team.Value == "R", you don't need to set it to "R" again.
  • teamtaking will change over time. If your flag function hasn't returned by that point, you will have multiple threads running your flag function simultaneously (which means your variables will get messed up in unexpected ways). You need to add debounce to fix this.
  • Theoretically, your function could be running for a long time (if teams keep fighting over flag). Roblox's lua does not support tail calls -- that is, your functions can't keep calling each other without ever returning (which yours could do -- you call flag from within flag). Instead, we'll wrap the inside of flag in a loop. We can break from the loop if we achieve the maximum desired value. To make this work, recordTeamIsCapturing will change to return true/false based on whether the team captured the flag or not (instead of calling wait(1)).

Resulting flag function:

local db = false
function flag()
    if db then return end
    db = true
    local captured
    while true do
        if teamtaking.Value == "R" and number ~= max then -- note: you didn't have "and number ~= max" here
            captured = recordTeamIsCapturing("R", BrickColor.new("Bright red"), Color3.new(1,0.137254902,0.137254902), 1, "rplayers")
            if captured then break end
        elseif teamtaking.Value == "B" and number ~= -max then
            captured = recordTeamIsCapturing("B", BrickColor.new("Bright blue"), Color3.new(0.137254902,0.137254902,1), -1, "bplayers")
            if captured then break end
        elseif teamtaking.Value == "N" then
            if team.Value == "R" and number ~= max then
                setNumber(number + 1)
                if number == max then break end
            elseif team.Value == "B" and number ~= -max then
                team.Value = "B"
                if number == -max then break end
            elseif team.Value == "N" then
                if number < 0 then
                    setNumber(number + 1)
                elseif number > 0 then
                    setNumber(number - 1)
                end
                if number == 0 then
                    flag.BrickColor = BrickColor.new("Institutional white")
                    poleTag.BackgroundColor3 = Color3.new(1,1,1)
                    break
                end
            end
        end
        wait(1)
    end
    db = false
end

--The final part of recordTeamIsCapturing now looks like this:

    if number == max * captureDir then
        team.Value = teamName
        return true
    else
        return false
    end

At this point we've fixed a few bugs, so that will probably fix your problem. My best guess is that teamtaking changes rapidly, causing your flag function to continue to increase number (since you don't have debounce in your original script). But say that this new script doesn't fix it? Start adding print statements in key places (ex at the beginning of flag and inside the while loop; maybe also before/after the wait). Make sure each print statement is unique, of course, so you can tell them apart (ex even just print(1), print(2), etc is fine, though more descriptive is easier when you're trying to figure out what it means in the output, like print("Beginning of flag"), print("flag: start of while loop")). The point of this is to figure out exactly which lines are/aren't running and why. ex, maybe your if statement isn't working as expected? Right before it runs, print out the values of the variables you use in it. Eventually you can narrow it down and figure out exactly what is wrong.

Full script on pastebin

0
Damn. That's a lot of words. CootKitty 311 — 6y
Ad

Answer this question