IsDescendantOf Doesn't Work

I’m trying to make something called the sticky bomb in my game, which is a bomb that can be thrown and then sticks to objects that it touches, and then it explodes.

I’m currently having an issue, where the bomb doesn’t consider the player’s character even though I tried filtering it out by checking if the part Is a Descendant of a part. The bomb for some reason would print that hit is indeed a descendant of the player’s character, but for some reason even though I made an if statement to not make a weld if the part is a descendant of the projectile/sticky bomb or the player’s character, even though it is printed that it is a descendant, the weld still gets created, and the elseif statement never goes through.

	local Connection
	Connection = missile.Touched:Connect(function(hit)
		print(hit:IsDescendantOf(player.Character)) -- Print's out as true, but then for some reason the script skips the elseif argument and for some reason makes a weld.
		if not hit:IsDescendantOf(player.Character) and not hit:IsDescendantOf(missile) then
			print("e")
			print(hit)
			Connection:Disconnect()
			local weld = Instance.new("WeldConstraint")
			weld.Parent = missile
			weld.Part0 = hit
			weld.Part1 = missile

			explode(missile, player)
		elseif hit:IsDescendantOf(player.Character) and hit:IsDescendantOf(missile) then
			print("true - weld not created")
		end
	end)
1 Like

Also BTW, nothing that is supposed to get printed after the initial if statement “e” and “hit” never gets printed, but the weld still gets created.

Could you show the whole script? It may have to do with missile

Sure, but I don’t think it does because the other part of the script is connected in a function that gets called and doesn’t have anything to do with the welds that are being created.

local Tool = script.Parent
local Ball = Tool.Handle
local RemoteEvent = Tool:WaitForChild("RemoteEvent")

local tickSound = Instance.new("Sound")
tickSound.SoundId = "rbxasset://sounds\\clickfast.wav"
tickSound.Parent = script.Parent

local explosionSound = Instance.new("Sound")
explosionSound.SoundId = "rbxassetid://4612378521"
explosionSound.Parent = script.Parent

local blastRegion3L = 12/2 -- The Length of the Blast (Dividing all of the dimensions by 2 so that the region3 is not twice its size after making its size relative to the position)
local blastRegion3W = 12/2 -- The Width of the Blast
local blastRegion3H = 12/2 -- The Maximum height of the region3

local baseDamage = 35

function explode(bomb, user)
	for i = 1, 3 do task.wait(.75)
		tickSound:Play()
	end

	task.wait(1)

	local explosionSoundClone = explosionSound:Clone()
	explosionSoundClone.Parent = bomb
	explosionSoundClone:Play()

	local region3 = Region3.new(
		bomb.Position - Vector3.new(blastRegion3L, blastRegion3H, blastRegion3W),
		bomb.Position + Vector3.new(blastRegion3L, blastRegion3H, blastRegion3W) 
	) -- Creates a region3 that destroys any parts in the explosions radius.

	local region3Visual = bomb.region3Visual:Clone()
	region3Visual.CFrame = region3.CFrame
	region3Visual.Parent = bomb

	region3Visual.Transparency = .5
	region3Visual.SelectionSphere.Transparency = .5

	region3Visual.Size = region3.Size

	local explosion = Instance.new("Explosion") -- The explosion instance
	explosion.Parent = bomb
	explosion.Position = region3Visual.Position
	explosion.BlastRadius = 0

	explosion.DestroyJointRadiusPercent = 0

	explosion.BlastRadius = blastRegion3L

	local overlapParams = OverlapParams.new()
	overlapParams.FilterDescendantsInstances = {region3Visual}

	local parts = workspace:GetPartBoundsInBox(region3.CFrame, region3.Size, overlapParams)

	explosion.Hit:Connect(function(Part)
		if Part.Name == "HumanoidRootPart" then
			local character = Part.Parent
			local player = game.Players:GetPlayerFromCharacter(character)

			if player and player.Team ~= user.Team then
				character:FindFirstChildOfClass("Humanoid"):TakeDamage(baseDamage)

				if character:FindFirstChildOfClass("Humanoid").Health == 0 then
					user.leaderstats.Kills.Value += 1
				end

			elseif player ~= user and player.Neutral == true then
				character:FindFirstChildOfClass("Humanoid"):TakeDamage(baseDamage)

				if character:FindFirstChildOfClass("Humanoid").Health == 0 then
					user.leaderstats.Kills.Value += 1
				end
			end
		end
	end)

	for i, v in pairs(parts) do
		if v.Name == "Brick" then
			v.Anchored = false

			v.CanTouch = false

			v.BrickColor = user.TeamColor

			for i, constraint in pairs(v:GetChildren()) do
				if constraint:IsA("Snap") or constraint:IsA("Weld") or constraint:IsA("WeldConstraint") then
					constraint:Destroy()
				end
			end

			task.delay(2, game.Destroy, v)
		end

		if v.Name == "GameBrick" then v.Name = "TaggedGameBrick" -- TaggedGameBricks are GameBricks in the game that have been effected by the bomb, while regular Bricks are just bricks you can destroy by default.
			v.Anchored = false

			v.CanTouch = false

			user.leaderstats.Bricks.Value += 1 -- The total bricks the player has broken throughout the round.
			user["T. Bricks"].Value += 1 -- The total bricks that the player has destroyed throughout there playtime
			user.leaderstats.Studs.Value += .1 -- Increases the players currency (Studs) by 0.1.
			v.BrickColor = user.TeamColor -- Changes the taggedBricks color to the local players team color to show that they have broken the part.

			task.delay(2, game.Destroy, v) -- later deletes the part.
		end
	end

	task.delay(3, game.Destroy, bomb)

	local tween = game:GetService("TweenService"):Create(region3Visual, TweenInfo.new(2, Enum.EasingStyle.Linear, Enum.EasingDirection.In, 0, false, 0), {
		Transparency = 1
	})

	tween:Play()

	local tween2 = game:GetService("TweenService"):Create(region3Visual.SelectionSphere, TweenInfo.new(2, Enum.EasingStyle.Linear, Enum.EasingDirection.In, 0, false, 0), {
		Transparency = 1
	}):Play()

	tween.Completed:Connect(function()
		task.delay(4, game.Destroy, region3Visual)
	end)

	task.wait(.5)
end

RemoteEvent.OnServerEvent:Connect(function(player, direction)
	local Character = Tool.Parent
	local Player = game.Players:GetPlayerFromCharacter(Character)

	local missile = Ball:Clone()
	missile.Parent = workspace.Bombs

	local spawnPos = Character.PrimaryPart.CFrame * CFrame.new(0, 0, -2.5)

	missile:PivotTo(spawnPos)
	missile.Velocity = direction * 200
	
	local new_script = script.CannonBall:Clone()
	new_script.Disabled = false
	new_script.Parent = missile
	
	local Connection
	Connection = missile.Touched:Connect(function(hit)
		print(hit:IsDescendantOf(player.Character))
		print(hit)
		if hit:IsDescendantOf(player.Character) == false and hit:IsDescendantOf(Tool) == false and hit:IsDescendantOf(workspace.Terrain) == false then
			print("e")
			print(hit)
			Connection:Disconnect()
			local weld = Instance.new("WeldConstraint")
			weld.Parent = missile
			weld.Part0 = hit
			weld.Part1 = missile

			explode(missile, player)
		elseif hit:IsDescendantOf(player.Character) and hit:IsDescendantOf(missile) then
			print("true - weld not created")
		end
	end)
end)

Why do you check if hit is a descendant of the missile? Isnt hit a body part

No, it isn’t. I’m trying to run test to see if hit is a part of the body, the tool, or parts of the handle. This is because for some reason every single time I use the tool, the tool automatically welds to parts located in the players handle.

you are using a conditional statement, due to the embedded logic of them, if it hits the descendant of the player and the missile its gonna run the statement. two falses make the statement true in an “if-and” statement. the and just means that both values have to be the SAME and if both are not true then they are both technically false. if they are both false they are true and the statement runs. hopefully that’s not too confusing

Maybe try changing the and for an or here:

elseif hit:IsDescesdantOf(player.Character) or hit:IsDescesdantOf(missile) then

I didn’t even think about that type of logic when I began even making this script… Thanks for pointing this out to me.

Do you think that using or’s instead of and’s would work?

think about it like this, an or in this case will be a 50% chance the statement runs. this is because at least one of the values needs to be true for an or statement to run. both values can be true, one can be true but both can’t be false. say if it hits a part of the player and you put the not there it reverses the value to false; and if it doesn’t hit the missile it’s gonna reverse that value too and make it true. it’s going to run if just ONE of the conditions is true or reversed to true. I don’t think or will work in your case the way you are using not

1 Like

Quite truthfully, I’m not an amazing scripter, but I feel like you should just use return rather than :Disconnect().

:Disconnect() stops the event from firing multiple times. return ends the function and or sends data back. in this case this is irrelevant to the issue at hand.

1 Like

couldnt he just do else if instead of elseif

What??

Please do not spread misinformation…

cc: @StarJ3M

if and statements only run when both values are true, not when they are the same value! What and does is check whether the two values are both “truthy”, AKA anything not false or nil, and gives true when they are, false when they aren’t, and if just checks whether it is also “truthy” before running the code.

1 Like

ohhh this is my fault, i was using my knowledge from java. the boolean tables in java says false and false makes true because they match. I assumed this applied here, sorry for the misunderstanding

yes it wouldn’t matter here it’s his choice

I tried using a more updated script, but for some reason one and two doesn’t get printed out at all and also even though Big_Green_Bumper as stated in the output is indeed a descendant and that "on " no weld was created, a weld is still created for some reason.

I take it back, I ended up finding out an old script of mine was creating welds and it didn’t have the updated version.

1 Like

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