Tool isn't deleting itself from player model or backpack when the player isn't sitting

Hello! In my game, I have a seat that gives a player a tool, and then deletes the tool when the player stands up. However, due to a necessary regen script that :Destroys()'s the seat’s model, regenerating the seat while a player is in it causes the tool to remain in the player’s inventory.

Therefor, I’m attempting to write a script inside the tool that destroys the tool when the Player Humanoid’s sitting state changes. I do this by checking for the tool both in the Player’s model and in the Player’s character

I’m using GetPropertyChangedSignal(“Parent”) to check when the tool is equipped/put in the Player’s backpack. I don’t check for the Player Humanoid’s Sit property because the path for the player changes depending on if the tool is equipped or not. Using my current method results in these issues:

  1. If the player has the tool equipped when the seat is destroyed and they stand up, the tool only destroys itself when they put it into their backpack.

  2. If the player has the tool in their backpack when the seat is destroyed and they stand up, the tool only destroys itself when they equip it.

I’m a programmer only by necessity, so I apologize if I’m missing an obvious solution. Here’s my code (forgive the mess):

local player = script.Parent.Parent.Parent
local tool = script.Parent
local char = tool.Parent


local function WeaponDestroy()
	--Check if tool is in backpack
	if tool.Parent.Name == "Backpack" then
		if player.Character.Humanoid.Sit == false then
			tool:Destroy()
		end
	else
	
	if tool:FindFirstAncestorWhichIsA("Model") then
			if tool:FindFirstAncestorWhichIsA("Model").Humanoid.Sit ~= true then
				tool:Destroy()
		end
	end
	end
end

tool:GetPropertyChangedSignal("Parent"):Connect(WeaponDestroy)

Any help would be appreciated—I was at this for 4 hours last night.

An alternative solution would be to go into the Seat’s script and check for Seat:Destroying to remove the player’s tools, but I didn’t write that script and I don’t feel confident messing around in it.

Why put the destroying logic in the tool? Just put it inside the seat itself.

script.Parent:GetPropertyChangedSignal("Occupant"):Connect(function()
	if script.Parent.Occupant == nil then return end
	local player = game.Players:GetPlayerFromCharacter(script.Parent.Occupant.Parent)
	
	if not player then return end
	
		local character = player.Character
		local backpack = player.Backpack
		local tool = game.StarterPack.Tool -- Your tool(I put this for testing purpouses)
		
	for i,v in character:GetChildren() do
		if v:IsA("Tool") and v.Name == tool.Name then v:Destroy() return end
	end
		
	for i,v in backpack:GetChildren() do
			if v:IsA("Tool") and v.Name == tool.Name then v:Destroy() return end
	end
	
end)

Thanks for your reply!

I see I only implied this in my post, but the reason I don’t put it inside of the seat is because the seat is being destroyed during the model regeneration. Your code above doesn’t run as-is (I did change the tool’s path to match the one it’s being cloned from, so if it triggered it would be comparing the right name).

However, it might work if I rewrite it to specifically trigger on Seat.Destroying:Connect(). I’ll mess around with it—unless you disagree?

How are you re generating the model? If you’re cloning it and parenting it to the workspace it shouldn’t be a problem.

That might work, try that out.

I clone a backup and parent it to a folder in workspace, yes.

Unfortunately my idea to connect the function to .Destroying didn’t work either. This is so frustrating—it feels like I’ve been dancing around an obvious solution for hours, haha.

Then it should work, if the script is inside the seat and the seat is inside the model. Did you try it out?

Yup! I’ve been trying your solution out (both the original and my modified one) as we’ve gone back-and-forth, as well as modifications to my original script.

What I’m beginning to arrive at is like… a script inside StarterPlayerScripts that triggers if Player.Character:GetPropertyChangedSignal("Sit) and Sit ~= true, which then loops through Player.Backpack and Player.Character for the tools to destroy. Something like

local player = script.Parent.Parent
local backpack = player.Backpack
local character = player.Character
local tool = game.ServerStorage.Cannon.Cannon

local SeatStatus = character.Humanoid

local function WeaponDestroy()
	
	if SeatStatus.Sit ~= true then
		
		for i,v in character:GetChildren() do
			if v:IsA("Tool") and v.Name == tool.Name then v:Destroy() return end
		end

		for i,v in backpack:GetChildren() do
			if v:IsA("Tool") and v.Name == tool.Name then v:Destroy() return end
		end
	
	
	else return end

end


SeatStatus:GetPropertyChangedSignal("Sit"):Connect(WeaponDestroy)

Unfortunately this doesn’t work either, but it does seem like another solution that almost works :confused:

(Sorry for the late reply)
Interesting, is your script a server script?

Are you doing this locally?

And are you getting any errors?

Also, this:

if SeatStatus.Sit ~= true then

its the same as:

if SeatStatus.Sit == false then

use the second method, its simpler to understand.

if not SeatStatus.Sit then

Try FindFirstAncestorOfClass
I had this problem once but doing FindFirstAncestorWhichIsA("Model") picks the workspace, Workspace | Documentation - Roblox Creator Hub


Try using Humanoid.StateChanged

Forget about what I said here’s my code that works:
Server Script in tool:

local LocalPlayer = script:FindFirstAncestorWhichIsA("Player")
local Tool = script.Parent

local Character = LocalPlayer.Character or LocalPlayer.CharacterAdded:Wait()
local Humanoid = Character:WaitForChild("Humanoid")

local function CheckState()
	if not Humanoid.Parent or not Humanoid.Sit or Tool.Parent:IsA("Backpack") then
		Tool:Destroy()
	end
end

Humanoid:GetPropertyChangedSignal("Sit"):Connect(function()
	CheckState()
end)

Tool:GetPropertyChangedSignal("Parent"):Connect(function()
	CheckState()
end)

Server Script in Seat:

script.Parent:GetPropertyChangedSignal("Occupant"):Connect(function()
	local Occupant = script.Parent.Occupant
	if Occupant then
		local NewTool = script.Tool:Clone()
		NewTool.Parent = Occupant.Parent
		
		Occupant:EquipTool(NewTool)
		NewTool.tool.Enabled = true
	end
end)

No problem! I appreciate any help I can get after being stuck on this for so long.

I’ve run the new script in StarterPlayerScripts both as a legacy and local script, to no avail. Both times, no errors were generated.

And yes, you are absolutely correct about those being the same—a remnant of my frenzied programming last night :sweat_smile: My bad.

Let me get to these other replies…

1 Like

Try using a normal/server script in just the seat itself, my version just works vanilla if its set up like that. Im also afraid if you delete the tools in the client they might stay on the server, might cause some problems in the future.

I guess try it out like that, I don’t know what else might fix it.

Thanks for your reply! I got help with a solution, but just FYI your tool script fires as the player enters the seat, so it destroys the tool too early.

Not for me, the script is enabled after the player is seated, you can add a wait

Hey folks! Thank you @JAcoboiskaka1121 and @ParadoxAssets for your assistance. I reached out to @Bounded_Toast and he arrived at this, which is a script that goes inside the tool:

local LocalPlayer = script:FindFirstAncestorWhichIsA("Player")
local Tool = script.Parent

local Character = LocalPlayer.Character or LocalPlayer.CharacterAdded:Wait()
local Humanoid = Character:WaitForChild("Humanoid")

local function CheckState()
    if not Humanoid.Sit then
      Tool:Destroy()
    end
end

Humanoid:GetPropertyChangedSignal("Sit"):Connect(CheckState)

This works, and is a lot simpler than the solutions I was brainstorming. If nothing else, all my troubleshooting taught me a lot about methods like GetPropertyChangedSignal and the best way to locate the player. Thank you all for your help as I learn what exactly I’m doing here.

2 Likes