Well I thought that would be how you could find the part the player touched…
part.Hit:Connect()
has automatically passes the part the object hit as the first argument.
local debounce = false
part.Hit:Connect(function(partthatithit)
if debounce then return end
debounce = true
-- rest of the code
debounce = false
end)
Does that mean the crystal, or the character?
if the part is the crystal, then hit is an instance descended from the character.
-- Take the crystal that was touched as an argument
local function crystalTouched(crystal, hit)
if not deb then
if hit.Parent:FindFirstChild("Humanoid") then
local plr = game.Players:GetPlayerFromCharacter(hit.Parent)
local crystals = plr:WaitForChild('leaderstats').Crystals
crystals.Value = crystals.Value + (1 * plr:WaitForChild("Gamepasses").CrystalsMultiplier.Value)
deb = true
-- We can use the crystal that was touched since we already know which crystal it is
crystal.Parent = crystalFolder
--wait(math.random(10,20))
wait(1) -- for testing purposes
crystal.Parent = workspace
setRandomPosition(crystal)
deb = false
end
end
end
for i, crystal in pairs(workspace:GetChildren()) do
if crystal.Name == "Crystal" then
-- Using an anonymous function here to pass the crystal that was touched
crystal.Touched:Connect(function(hit) crystalTouched(crystal, hit) end)
end
end
I would use an anonymous function to pass the crystal that was touched as well as the part that touched it.
This is slightly unrelated but I prefer using debounces like this:
function debounce(func)
local running = false
return function(...)
if not running then
running = true
func(...)
running = false
end
end
end
This function was pulled from the bottom of roblox’s article on debounce and it makes .Touched connections look much cleaner. This is how you use it:
part.Touched:Connect(debounce(function(hitPart)
-- now you don't need anything related to debounce in here
end)) -- don't forget the extra ) from the debounce()
uhh…
local rs = game.ReplicatedStorage
local crystalFolder = rs.Crystals
local deb = false
local RNG = Random.new()
local bases = {
{Object = workspace.Ground.Grass, Weight = 5};
{Object = workspace.Path, Weight = 2};
}
local function random(choices)
local weightSum = 0
for i = 1, #choices do
weightSum = weightSum + choices[i].Weight
end
local rand = RNG:NextInteger(0, weightSum)
for i = 1, #choices do
if rand <= choices[i].Weight then
return choices[i].Object
end
rand = rand - choices[i].Weight
end
end
local function setRandomPosition(item)
local Base = random(bases)
item.CFrame = CFrame.new(
RNG:NextInteger((-Base.Size.X / 2), (Base.Size.X / 2)),
Base.Position.Y + (Base.Size.Y / 2) + (item.Size.Y / 2),
RNG:NextInteger((-Base.Size.Z / 2), (Base.Size.Z / 2))
) * CFrame.Angles(0, math.rad(RNG:NextInteger(0, 360)), 0)
end
local function crystalTouched(crystal, hit)
if not deb then
if hit.Parent:FindFirstChild("Humanoid") then
local plr = game.Players:GetPlayerFromCharacter(hit.Parent)
local crystals = plr:WaitForChild('leaderstats').Crystals
crystals.Value = crystals.Value + (1 * plr:WaitForChild("Gamepasses").CrystalsMultiplier.Value)
deb = true
crystal.Parent = crystalFolder
print("Yay")
--wait(math.random(8,20))
wait(1)
print("Waited")
crystal.Parent = workspace
setRandomPosition(crystal)
deb = false
end
end
end
for i, crystal in pairs(workspace:GetChildren()) do
if crystal.Name == "Crystal" then
crystal.Touched:Connect(function(hit)
crystalTouched(crystal, hit)
end)
end
end
I got print statements in the output but then I think the bases disappeared.
I also got this error again! (yay)
attempt to call a nil value
in between the two print statements.
local rs = game.ReplicatedStorage
local crystalFolder = rs.Crystals
local deb = false
local RNG = Random.new()
local bases = {
{Object = workspace.Ground.Grass, Weight = 5};
{Object = workspace.Path, Weight = 2};
}
local function random(choices)
local weightSum = 0
for i = 1, #choices do
weightSum = weightSum + choices[i].Weight
end
local rand = RNG:NextInteger(0, weightSum)
for i = 1, #choices do
if rand <= choices[i].Weight then
return choices[i].Object
end
rand = rand - choices[i].Weight
end
end
local function setRandomPosition(item)
local Base = random(bases)
item.CFrame = CFrame.new(
RNG:NextInteger((-Base.Size.X / 2), (Base.Size.X / 2)),
Base.Position.Y + (Base.Size.Y / 2) + (item.Size.Y / 2),
RNG:NextInteger((-Base.Size.Z / 2), (Base.Size.Z / 2))
) * CFrame.Angles(0, math.rad(RNG:NextInteger(0, 360)), 0)
end
local function crystalTouched(crystal, hit)
if not deb then
deb = true
if hit.Parent:FindFirstChild("Humanoid") then
local plr = game.Players:GetPlayerFromCharacter(hit.Parent)
local crystals = plr:WaitForChild('leaderstats').Crystals
crystals.Value = crystals.Value + (1 * plr:WaitForChild("Gamepasses").CrystalsMultiplier.Value)
crystal.Parent = crystalFolder
print("Yay")
--wait(math.random(8,20))
wait(1)
print("Waited")
crystal.Parent = workspace
setRandomPosition(crystal)
deb = false
end
end
end
for i, crystal in pairs(workspace:GetChildren()) do
if crystal.Name == "Crystal" then
crystal.Touched:Connect(function(hit)
crystalTouched(crystal, hit)
end)
end
end
Try this.
I moved the deb = true
to the top of the if statement. There will be a fraction of a second of lag while assigning the variables because you used :WaitForChild()
and :GetPlayerFromCharacter()
. During this time, a new .Touched
even could have fired on the same crystal, and since deb
is not set to true
yet, the function executes.
Ok it worked but the bases are still disappearing along with the other crystals.
The bases should just be transparent CanCollide = false
rectangles that mark the areas where the crystals can spawn. You’re not supposed to be able to see them.
ohhhh… that’s why.
If the problem is fixed you can mark the answer that fixed it for you as the solution. It will help others when they view the thread by allowing them to jump straight to the answer rather than read through every reply.
One problem still:
The grass keeps moving as well as crystals that were not touched:
local crystalFolder = game.ServerStorage.Crystals
local deb = false
local RNG = Random.new()
local bases = {
{Object = workspace.Base, Weight = 3};
{Object = workspace.Base2, Weight = 4};
}
local function random(choices)
local weightSum = 0
for i = 1, #choices do
weightSum = weightSum + choices[i].Weight
end
local rand = RNG:NextInteger(0, weightSum)
for i = 1, #choices do
if rand <= choices[i].Weight then
return choices[i].Object
end
rand = rand - choices[i].Weight
end
end
local function setRandomPosition(item)
local Base = random(bases)
item.CFrame = CFrame.new(
RNG:NextInteger((-Base.Size.X / 2), (Base.Size.X / 2)),
Base.Position.Y + (Base.Size.Y / 2) + (item.Size.Y / 2),
RNG:NextInteger((-Base.Size.Z / 2), (Base.Size.Z / 2))
) * CFrame.Angles(0, math.rad(RNG:NextInteger(0, 360)), 0)
end
local function crystalTouched(crystal, hit)
if not deb then
deb = true
if hit.Parent:FindFirstChild("Humanoid") then
local plr = game.Players:GetPlayerFromCharacter(hit.Parent)
local crystals = plr:WaitForChild('leaderstats').Crystals
crystals.Value = crystals.Value + (1 * plr:WaitForChild("Gamepasses").CrystalsMultiplier.Value)
crystal.Parent = crystalFolder
print("Yay")
--wait(math.random(8,20))
wait(1)
print("Waited")
crystal.Parent = workspace
setRandomPosition(crystal)
deb = false
else
deb = false
end
end
end
script.Parent.Touched:Connect(function(hit)
crystalTouched(script.Parent, hit)
end)
Note: I moved the script into every crystal.
It works again after I deleted some welds. (Idk how that does anything but whatever maybe I’m dumb)
One thing though: some crystals appear in the tycoons which could be bad.
That probably means that a part of one of the bases is in the tycoon.