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

Help With Ipairs Script?

Asked by
Scootakip 299 Moderation Voter
8 years ago

I have this script which works find except for one thing that I don't know how to fix. At one part of the script, it generates a number, either 1 or 2, and that number is the one that decides which map is loaded, the only problem is that with multiple people the value seems to have multiple numbers somehow and it calls for more than one map. How can I fix this? I'm using intvalue as the value for the map number, if that's what's causing the problem.

gm = game.Workspace.GMstat.Intermission

while true do
ToMapOne = CFrame.new(-2, 20.5, -50)
ToMapTwo = CFrame.new(-27, 69.5, 18)
ToSpawn = CFrame.new(277.5, 1.5, -206.5)
mapc = game.Workspace.MapNum.Value
wait(29)
gm.Name = "Game In Progress"
for i, player in ipairs(game.Players:GetChildren()) do
   if player.Character and player.Character:FindFirstChild("Torso") then
    mapc.Value = (math.random(2))
    wait(1)
    if mapc.Value == 1 then
      print(mapc.Value)
      player.Character.Torso.CFrame = ToMapOne + Vector3.new(0, i * 5, 0)
      player.TeamColor = game.Teams["Playing"].TeamColor
        for i, m1 in ipairs(game.Workspace.MapOne:GetChildren()) do
    m1.Transparency = 0
    m1.CanCollide = true
end
        end 
    if mapc.Value == 2 then
        print(mapc.Value)
        player.Character.Torso.CFrame = ToMapTwo + Vector3.new(0, i * 5, 0)
        player.TeamColor = game.Teams["Playing"].TeamColor
        for i, m2 in ipairs(game.Workspace.MapTwo:GetChildren()) do
    m2.Transparency = 0
    m2.CanCollide = true
end
    end 
    end  
end
wait(60)
gm.Name = "Intermission"
for i, m1 in ipairs(game.Workspace.MapOne:GetChildren()) do
    m1.Transparency = 1 
    m1.CanCollide = false
end
for i, m2 in ipairs(game.Workspace.MapTwo:GetChildren()) do
    m2.Transparency = 1 
    m2.CanCollide = false
end
for i, player in ipairs(game.Players:GetChildren()) do
      if player.Character and player.Character:FindFirstChild("Torso") then
           player.TeamColor = game.Teams["Lobby"].TeamColor
           player.Character.Torso.CFrame = ToSpawn + Vector3.new(0, i * 5, 0)
end
     end
end

1 answer

Log in to vote
0
Answered by
BlueTaslem 18071 Moderation Voter Administrator Community Moderator Super Administrator
8 years ago

Tab your code correctly.

Currently, your code reads like this:

  • For each player
    • ... select a random map, and build it
    • teleport that player

Obviously, the second step is in the wrong place.

Notice how mapc and related is inside the loop, but doesn't use player or i at all? That's a hint that's in the wrong place.

First, though, some cleanup.

  • Use elseif mapc.Value == 2 instead of end if mapc.Value == 2. This is cleaner, briefer, and better shows that the two cases are mutually exclusive.

  • Now, you can see that most of the code is the same between the two then blocks. Don't repeat yourself. Pull it out if it's the same.

Looks something like this:

            local teleport, map
            print(mapc.Value)
            if mapc.Value == 1 then
                teleport = ToMapOne
                map = workspace.MapOne
            elseif mapc.Value == 2 then
                teleport = ToMapTwo
                map = workspace.MapTwo
            end
            for _, part in pairs(map:GetChildren()) do
                part.Transparency = 0
                part.CanCollide = true
            end
            player.TeamColor = game.Teams["Playing"].TeamColor
            player.Character.Torso.CFrame = teleport + Vector3.new(0, i * 5, 0)

You don't need to use ipairs if the order doesn't matter -- just use pairs -- it indicates that meaning better. Also, you should be careful that all of the children of the map are actually parts, and aren't, for instance, grouped.


The above code still needs to have the map-selection-code pulled out. It's a lot easier now, though, since just the last two lines use player:

    mapc.Value = math.random(2)
    wait(1)
    print(mapc.Value)
    local teleport, map
    if mapc.Value == 1 then
        teleport = ToMapOne
        map = workspace.MapOne
    elseif mapc.Value == 2 then
        teleport = ToMapTwo
        map = workspace.MapTwo
    end
    for _, part in pairs(map:GetChildren()) do
        part.Transparency = 0
        part.CanCollide = true
    end
    for i, player in pairs(game.Players:GetChildren()) do
        if player.Character and player.Character:FindFirstChild("Torso") then
            player.TeamColor = game.Teams["Playing"].TeamColor
            player.Character.Torso.CFrame = teleport + Vector3.new(0, i * 5, 0)
        end
    end
    wait(60)

The cleanup code repeats itself, too. You only need to hide the map that just played:

    wait(60)
    gm.Name = "Intermission"
    for _, part in pairs(map:GetChildren()) do
        part.Transparency = 1 
        part.CanCollide = false
    end

Your code would look even better if you use functions to break it up.

Other Suggestions

I'm guessing you don't want to set the Name of gm. It probably makes more sense to be setting Text or Value, depending on what it is.

mapc doesn't really need to be an IntValue. You could just have a variable for the index.

Instead of using elseifs on the mapc, you could use a dictionary of map & teleport location, or make the teleport location a part of the map (e.g., have a part named "SpawnLocation" in it that you look for)

I imagine a final cleanup looking something like this:

gm = game.Workspace.GMstat.Intermission

function hideMap(map)
    for _, part in pairs(map:GetChildren()) do
        part.Transparency = 1
        part.CanCollide = false
    end
end

function showMap(map)
    for _, part in pairs(map:GetChidren()) do
        part.Transparency = 0
        part.CanCollide = true
    end
end

-- Returns the list of players with torso
function alivePlayers()
    local t = {}
    for _, player in pairs(game.Players:GetPlayers()) do
        if player.Character and player.Character:FindFirstChild("Torso") then
            table.insert(t, player)
        end
    end
    return t
end

-- Teleports all living players to CFrame to
-- Sets the teamcolor of all living players to `teamcolor`
function teleportPlayers(to, teamcolor)
    for i, player in pairs(alivePlayers()) do
        player.TeamColor = teamcolor
        player.Character.Torso.CFrame = to + Vector3.new(0, i * 5, 0)
    end
end

ToSpawn = CFrame.new(277.5, 1.5, -206.5)
MapSpawns = {
    [1] = CFrame.new(-2, 20.5, -50),
    [2] = CFrame.new(-27, 69.5, 18),
}
Maps = {
    [1] = workspace.MapOne,
    [2] = workspace.MapTwo,
}

while true do
    wait(29)
    gm.Name = "Game In Progress"
    wait(1)
    local mapc = math.random(2)
    local teleport = MapSpawns[mapc]
    local map = Maps[mapc]
    showMap(map)
    teleportPlayers(teleport, game.Teams.Playing.TeamColor)
    wait(60)
    gm.Name = "Intermission"
    hideMap(map)
    teleportPlayers(ToSpawn, game.Teams.Lobby.TeamColor)
end

Though I think you have a mistake in thinking that you can just reset the teamcolor of alive players back to Lobby. I think you want to reset all players.

0
Still doesn't work. Some error at line 52 Scootakip 299 — 8y
0
I had a typo. Just read the code, it shouldn't be hard to figure out. Not to mention *only* the final, total rewrite had the mistake. Read the answer, while you're at it. BlueTaslem 18071 — 8y
Ad

Answer this question