Please help me with my part limiter

Greetings,

I have made a part spawning system for my simulator, though the limiter doesn’t work. maxparts should’ve been the variable that was to stop and restart the system at a cap of 100 maximum parts. The Reset event is whenever a player touches a spawned part. The script is a server script stored in server script service. The last part of the script seems to not work at all (When the Reset event has to be received by the script). Please help! The script is attached down below

local RS = game:GetService("ReplicatedStorage")
local Reset = RS:WaitForChild("Adding"):WaitForChild("Speed")

local storage = game:GetService("ServerStorage").SpeedParts
local speed1 = storage:WaitForChild("1Speed")
local speed5 = storage:WaitForChild("5Speed")
local speed10 = storage:WaitForChild("10Speed")

local quarter1 = workspace.Quarter1
local quarter2 = workspace.Quarter2
local quarter3 = workspace.Quarter3
local quarter4 = workspace.Quarter4
local quarter5 = workspace.Quarter5

local maxparts = 0

local function partRegen()
	while maxparts < 100 do
		local partchance = math.random(1,10)
		local chosenpart
		if partchance <= 5 then
			chosenpart = speed1
		elseif partchance <= 8 and partchance > 5 then
			chosenpart = speed5
		elseif partchance <= 10 and partchance > 8 then
			chosenpart = speed10
		end
		local quarter = math.random(1,5)
		local chosenquarter
		local pos1
		local pos2
		if quarter == 1 then
			chosenquarter = quarter1
			pos1 = math.random(-100,100)/100 * chosenquarter.Size.X/2
			pos2 = math.random(-100,100)/100 * chosenquarter.Size.Z/2
		elseif quarter == 2 then
			chosenquarter = quarter2
			pos1 = math.random(-100,100)/100 * chosenquarter.Size.X/2
			pos2 = math.random(-100,100)/100 * chosenquarter.Size.Z/2
		elseif quarter == 3 then
			chosenquarter = quarter3
			pos1 = math.random(-100,100)/100 * chosenquarter.Size.X/2
			pos2 = math.random(-100,100)/100 * chosenquarter.Size.Z/2
		elseif quarter == 4 then
			chosenquarter = quarter4
			pos1 = math.random(-100,100)/100 * chosenquarter.Size.X/2
			pos2 = math.random(-100,100)/100 * chosenquarter.Size.Z/2
		elseif quarter == 5 then
			chosenquarter = quarter5
			pos1 = math.random(-100,100)/100 * chosenquarter.Size.X/2
			pos2 = math.random(-100,100)/100 * chosenquarter.Size.Z/2
		end
		local copypart = chosenpart:Clone()
		copypart.Parent = workspace.SpeedParts
		copypart.Position = chosenquarter.Position + Vector3.new(pos1, 1, pos2)
		maxparts += 1
		print("There are now:  " ..maxparts)
		wait(3.5)
	end
end

partRegen()

Reset.Event:Connect(function()
	maxparts -= 1
	print("There are now: " ..maxparts)
	
	partRegen()
end)

I don’t see anything wrong right off the bat, but you can simplify the code a bit.

Do you see a pattern here?

For starters, no matter which quarter you have chosen, this is executed:

This means you can factor that out, which leaves us with

-- Simplified stage 1:
if quarter == 1 then
	chosenquarter = quarter1
elseif quarter == 2 then
	chosenquarter = quarter2
elseif quarter == 3 then
	chosenquarter = quarter3
elseif quarter == 4 then
	chosenquarter = quarter4
elseif quarter == 5 then
	chosenquarter = quarter5
end

pos1 = math.random(-100,100)/100 * chosenquarter.Size.X/2
pos2 = math.random(-100,100)/100 * chosenquarter.Size.Z/2

Now, do you see an additional pattern? If quarter == 1, then you want quarter1. This pattern holds for all of your quarters, and since they are found in the workspace by this name you can do this:

-- Simplified stage 2:
local chosenQuarter = workspace:FindFirstChild("Quarter" .. math.random(1, 5))

local pos1 = math.random(-100,100)/100 * chosenQuarter.Size.X/2
local pos2 = math.random(-100,100)/100 * chosenQuarter.Size.Z/2

Keeping data & code separate

This code works, but you are now mixing data and code. What chance something has of happening is data, which means it should be read from elsewhere and then handled in the code. I think you should make a table which has the probability of each part being chosen, and then have a code to determine which should be chosen based off of that.

Simplified code:

local RS = game:GetService("ReplicatedStorage")
local Reset = RS:WaitForChild("Adding"):WaitForChild("Speed")

local storage = game:GetService("ServerStorage").SpeedParts


local speedLookup = {
	[5] = storage:WaitForChild("1Speed"), -- Chance of getting it (50%)
	[3] = storage:WaitForChild("5Speed"), -- 30%
	[2] = storage:WaitForChild("10Speed") -- 20%
}


local maxparts = 0

local function partRegen()
	while maxparts < 100 do
		local partchance = math.random(1,10)
		local chosenPart = nil
		
		local previousPart = nil
		for chance, speed in pairs(speedLookup) do
			if partchance > chance then
				previousPart = speed
			else
				chosenPart = previousPart
				break
			end
		end
		
		
		local chosenQuarter = workspace:FindFirstChild("Quarter" .. math.random(1, 5))

		local pos1 = math.random(-100,100)/100 * chosenQuarter.Size.X/2
		local pos2 = math.random(-100,100)/100 * chosenQuarter.Size.Z/2
		
		local copypart = chosenPart:Clone()
		copypart.Position = chosenQuarter.Position + Vector3.new(pos1, 1, pos2)
		copypart.Parent = workspace.SpeedParts

		maxparts += 1
		print("There are now:  " ..maxparts)
		wait(3.5)
	end
end

partRegen()

Reset.Event:Connect(function()
	maxparts -= 1
	print("There are now: " ..maxparts)

	partRegen()
end)
4 Likes

Hey,

I get an error at line 37 that is:
local copypart = chosenPart:Clone()

Is it because you’ve set chosenPart to nil before that?

What do you mean the Reset event doesn’t work? What do you expect to happen vs what is really happening? What errors are you getting? If it is based on a .Touched input then it will fire many times per touch.

Nope, still getting the same error

It simply doesn’t do anything, and I am getting no errors. The part disappears on touch and it doesn’t do it multiple times since the points are added correctly to the player that did so. What should happen is what you see in the script. The maxparts stopping the script when it hits 100 and when it changes it checks if its under 100 or not and it does its job.

For troubleshooting try printing the values that each section is checking for. For example add this before line 37:
print chosenPart
local copypart = chosenPart:Clone()


:confused: nothing else printed sadly

Why don’t you create a folder that all the parts go in on the client side and then you can loop through it with a variable. And then you can do if tonumber(CurrentPartCount) > MaxParts then print("Max parts")
Your basically creating a number variable and then your looping through the folder with all the parts in it for the client side and every time it finds a part it adds to the variable by 1. Then you can do a while true do loop to check if the variable is over the maximum amount of parts. it’s that simple.

What is calling your partRegen() function. You fire it once the first time the script runs.
You then call it when Reset.Event: is fired, so obviously that isn’t firing your function. Look into what’s going on there.