Skip to content

Instantly share code, notes, and snippets.

@katsaii
Last active January 3, 2022 21:00
Show Gist options
  • Save katsaii/05a405ed4f5aca2c068042c07fa2cbc6 to your computer and use it in GitHub Desktop.
Save katsaii/05a405ed4f5aca2c068042c07fa2cbc6 to your computer and use it in GitHub Desktop.
A script for Roblox games that spawns parts within regions defined by `Start` and `End` controlpoints
local manager = script.Parent
-- helper function for colliding with humanoids
local function TouchedHumanoid(f)
return function(collider)
local parent = collider.Parent
if parent:FindFirstChildWhichIsA("Humanoid") then
f(parent)
end
end
end
-- track button state
local enabled = false
local button = manager.ButtonToggle
local pause = false
local function UpdateButtonState()
if enabled then
print("ENABLE: " .. manager.Name)
button.BrickColor = BrickColor.new("Dark green")
else
print("DISABLE: " .. manager.Name)
button.BrickColor = BrickColor.new("Tr. Red")
end
end
UpdateButtonState()
button.Touched:Connect(TouchedHumanoid(function(player)
if pause then
return
end
pause = true
enabled = not enabled
UpdateButtonState()
wait(1) -- second
pause = false
end))
-- loop through all regions we need to spawn particles for
local regions = { }
local mag_total = 0
for i, model in ipairs(manager.Regions:GetChildren()) do
-- set each region to be invisible to players
for _, child in ipairs(model:GetChildren()) do
child.CanCollide = false
child.Anchored = true
child.CanTouch = false
child.Transparency = 1.0
end
-- calculate region data
local pos_start = model.Start.Position
local pos_end = model.End.Position
local mag = (pos_end - pos_start).Magnitude
regions[i] = {
Part = model,
MinPos = Vector3.new(
math.min(pos_start.X, pos_end.X),
math.min(pos_start.Y, pos_end.Y),
math.min(pos_start.Z, pos_end.Z)),
MaxPos = Vector3.new(
math.max(pos_start.X, pos_end.X),
math.max(pos_start.Y, pos_end.Y),
math.max(pos_start.Z, pos_end.Z)),
Probability = mag,
}
mag_total = mag_total + mag
end
if mag_total > 0 then
-- normalise probabilities
for _, region in ipairs(regions) do
region.Probability = region.Probability / mag_total
end
end
-- handle the creation of new parts
local part_count = 0
local part_limit = 100
local function SpawnRandomParts()
if part_count >= part_limit then
return
end
for i, region in ipairs(regions) do
if math.random() > region.Probability then
continue
end
-- spawn a new part within this region
part_count = part_count + 1
local random_pos = Vector3.new(
math.random(region.MinPos.X, region.MaxPos.X),
math.max(region.MinPos.Y, region.MaxPos.Y),
math.random(region.MinPos.Z, region.MaxPos.Z))
local new_part = Instance.new("Part")
new_part.Parent = region.Part
new_part.Position = random_pos
new_part.Size = Vector3.new(1, 1, 1)
new_part.Shape = "Ball"
new_part.Anchored = true
-- delete the part if the player touches it
new_part.Touched:Connect(TouchedHumanoid(function(player)
part_count = part_count - 1
new_part:Destroy()
end))
end
end
-- spawn a service that creates parts periodically whilst active
local run_service = game:GetService("RunService")
local current_time = 0
local duration = 0.5 -- second
run_service.Heartbeat:Connect(function(delta_time)
if not enabled then
return
end
current_time = current_time + delta_time
if current_time >= duration then
current_time = current_time - duration
SpawnRandomParts()
end
end)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment