What am I doing wrong in this script?

local debounce = false
local count = 1
local serverStorage = game:GetService("ServerStorage")
local players = game:GetService("Players")

function findTorso(pos)
	local torso = nil
	local dist = 1000000000000000000
	local child = workspace:GetDescendants()
	for i=1, #child do
		if child[i].className == "Model" and child[i] ~= script.Parent.Parent and child[i]:FindFirstChild("NPCTAG") == nil then
			local h = child[i]:findFirstChild("Humanoid")
			if h ~= nil then
				local check = child[i]:findFirstChild("Head")
				if check ~= nil and check.Parent.Name ~= "Souls" and check.Anchored == false and h.Health ~= math.huge then
					if (check.Position - pos).magnitude < dist then
						torso = check
					end
				end
			end
		end
	end
	return torso
end

while true do
	if debounce == false then
		debounce = true
		spawn(function()
			task.wait(4)
			local GB = serverStorage.BLASTER:Clone()
			GB.Parent = workspace
			GB:WaitForChild("Script").Disabled = false
			GB:SetPrimaryPartCFrame(GB:GetPrimaryPartCFrame() * CFrame.new(Vector3.new(-275,275),0,math.random(-275,275)))
			local player = workspace:FindFirstChildOfClass("Player")
			local torso = findTorso(player.Character)
			if torso ~= nil then
				GB.CFrame = CFrame.new(GB.Position, torso.Position)
			end
			task.wait(0.2)
			debounce = false
		end)
	end
	task.wait(0.01)
end

Ignore the count variable, that is not really needed and is more of when I’m using a repeat until statement.

For context, I’m trying to make it so that after a certain amount of time, a model (BLASTER) cloned from serverStorage to be set to workspace and sets the CFrame on a player’s position only once. That part works, including the randomized position. However, the underlying problem starts from these parts.

local player = workspace:FindFirstChildOfClass("Player")
			local torso = findTorso(player.Character)
			if torso ~= nil then
				GB.CFrame = CFrame.new(GB.Position, torso.Position)
			end
function findTorso(pos)
	local torso = nil
	local dist = 1000000000000000000
	local child = workspace:GetDescendants()
	for i=1, #child do
		if child[i].className == "Model" and child[i] ~= script.Parent.Parent and child[i]:FindFirstChild("NPCTAG") == nil then
			local h = child[i]:findFirstChild("Humanoid")
			if h ~= nil then
				local check = child[i]:findFirstChild("Head")
				if check ~= nil and check.Parent.Name ~= "Souls" and check.Anchored == false and h.Health ~= math.huge then
					if (check.Position - pos).magnitude < dist then
						torso = check
					end
				end
			end
		end
	end
	return torso
end

The part above was taken from a free model script, which apparently doesn’t also work even on the original state and I do not know how to modify both the script for finding the torso and the script that makes it so the model’s CFrame is directed towards a player’s position to make it work and I’ve tried a few methods but to no avail. I don’t know how to solve the problem so I’m asking for help. If anyone would help, please do so. I’d greatly appreciate it!

1 Like

I’m not sure if this is the problem but it’s something wrong

you are trying to find a player instance in the workspace, but the workspace is not where the players are stored

why exactly are you checking for distance when you want it to be infinite?

torso = check

you’re also using the deprecated version of :FindFirstChild()

local h = child[i]:findFirstChild("Humanoid")
...
local check = child[i]:findFirstChild("Head")
1 Like

The part above was taken from a free model script, which apparently doesn’t also work even on the original state and I do not know evmodify both the script for finding the torso and the script that makes it so the model’s CFrame is directed towards a player’s position to make it work and I’ve tried a few methods but to no avail.

I have said this before but if it is not necessary, I will remove it.

i didn’t really read all of it sorry

Am I supposed to get the player’s head or any part through finding the player in playerservice and then getting the player’s position?

1 Like

What happens is that the player character is in the workspace, not the player himself, you are using the FindFirstChildOfClass function which is used to find an instance of a specific class, and the player character is an instance of type model, not player

1 Like

So what should I do in this case? Should I get the player’s character through Players to get the singular character or continue finding the player’s model in workspace but change the code?

If you want to access the player then you should not search in the workspace, but rather where it says Players, in that line of code you are looking in the workspace for an instance of type player, which you will never find

It’s up to you, really. You need to decide when and for whom this script will run. For example, you could run it whenever a player joins (Players.PlayerAdded), or when the user triggers some prompt (ProximityPrompt.Triggered).

I don’t know if it has to do with the script I’m trying to debug but I’ll explain what I’m trying to do again.

For context, I’m trying to make it so that after a certain amount of time, a model (BLASTER) cloned from serverStorage to be set to workspace and sets the CFrame on a player’s position only once.

TL:DR, After 4 seconds, a blaster model will be cloned which the primarypart’s CFrame will cause the blaster to turn the CFrame towards the player’s model position when there is a player in the game.

I’ve also tried another version of your advice.

while true do
	if debounce == false then
		debounce = true
		spawn(function()
			task.wait(4)
			local GB = serverStorage.BLASTER:Clone()
			GB.Parent = workspace
			GB:WaitForChild("Script").Disabled = false
			GB:SetPrimaryPartCFrame(GB:GetPrimaryPartCFrame() * CFrame.new(Vector3.new(math.random(-275,275),0,math.random(-275,275))))
			print("PASSED")
			players.PlayerAdded:Connect(function(player)
				print("PASSED2")
				local torso = findTorso(player.Character.PrimaryPart)
				if torso ~= nil then
					GB.CFrame = CFrame.new(GB.Position, torso.Position)
					print("PASSED3")
				end
			end)
			task.wait(0.2)
			debounce = false
		end)
	end
	task.wait(0.01)
end

players.PlayerAdded:Connect(function(player) Does not seem to run at all, judging from the 2nd print not appearing.

Say, was your actual goal to make some blaster point at the nearest player?

Yes. That was the goal. I did copy the code before you deleted it but I only ran into one error; that being if (check.Position - pos).magnitude then, where it said

ServerScriptService.DupeScript:16: attempt to perform arithmetic (sub) on Vector3 and Instance 

Almost forgot to mention, one time for local torso = findTorso(player.Character.PrimaryPart) showed a error but now its local torso = findTorso(player.Character) for that reason.

Ok. Let’s make some improvements in the code and execute the logic necessary for your use case.

First things first, we’ll need a function that returns a CFrame that corresponds to the nearest player.

local function nearestPlayerPos(origin: Vector3) : CFrame
    ...
end

To do this, we’ll loop through every player currently in the game (Players:GetPlayers()) and calculate the one with the smallest distance relative to the origin.

local Players: Players = game:GetService("Players");

local function nearestPlayerPos() : Vector3?
	local nearestPosition = nil;

	for _, player in Players:GetPlayers() do
		...
	end

	return nearestPosition
end

The logic will be to store a pair (smallest distance, nearest player position) and by looping through all the players’ characters, we’ll get the desired value.

local Players: Players = game:GetService("Players");

local function nearestPlayerPos(origin: Vector3) : Vector3?
	local nearestPosition: Vector3 = nil;
	local smallestDistance: number = math.huge;

	for _, player in Players:GetPlayers() do
		local character = player.Character

		if character then
			local hrp = character:FindFirstChild("HumanoidRootPart")

			if hrp then
				local distance = (hrp.Position - origin).Magnitude

				if distance < smallestDistance then
					smallestDistance = distance;
					nearestPosition = hrp.Position;
				end
			end
		end
	end

	return nearestPosition
end

It’s as if we were taking a minimum value inside a table. For example, { 5, 14, 9, 3, 19}. In fact, we could implement it like that, but this is more performant (even if the difference is not significant).

Now that we have the core of our script implemented, we can go to the loop part, where we only want one thing: to load a blaster that points to the nearest player.

Let’s firstly load it:

local ServerStorage: ServerStorage = game:GetService("ServerStorage")
local blaster = ServerStorage.Blaster -- use a proper naming convention

while true do
    task.wait(4) -- forgot to mention delay

	local clone = blaster:Clone()
	clone.Parent = workspace
	clone.Script.Disabled = false -- is this even necessary?
    ...
end

After this, we want to actually use the function we’ve coded. We do that by calculating the random CFrame and creating a new one from it that points to the nearest player’s character. After that, we use Model:SetPrimaryPartCFrame in order to make it face our target.

local randomCFrame = CFrame.new(
		Vector3.new(
			math.random(-275, 275),
			0,
			math.random(-275, 275)
		)
	);

	local npp = nearestPlayerPos(randomCFrame.Position)
	if npp then
		clone:SetPrimaryPartCFrame(CFrame.new(randomCFrame.Position, npp))
	end

And as easy as that. Two advices for you though:

  1. Don’t rely too much on free models. They’ve usually got outdated / unsafe / bad code. Either write it yourself or search for existing implementations here in the DevForums.
  2. Don’t just copy and paste. Actually interact with the code provided to you and work off of it.
  3. Ask questions.

Well it works. I feel pretty dumb that there are things I just can’t figure out that well and the overreliance of free models I still have/copy and pasting things (although I do interact with the code, I just copy the core that allows it to function and then put whatever that allows me to change the code without damaging the things that work inside of the code). Although at least it works, I’m starting to think that theres not enough knowledge I have in store to not use free models especially the tutorials.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.