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)
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:
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.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.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.