Help figuing out how to get parts that are touching hrp for script

You can write your topic however you want, but you need to answer these questions:

  1. What do you want to achieve? Keep it simple and clear!
    For the heat to go down unless if it is touching a part named ‘FireBox’

  2. What is the issue? Include screenshots / videos if possible!
    I cannot figure out how to get a list of all touching parts, always returns ‘Function’ is not a valid member of Part “Workspace.fetviper_4.HumanoidRootPart”

  3. What solutions have you tried so far? Did you look for solutions on the Developer Hub?
    Yes, and even the official documentation. Nothing so far.

After that, you should include more details if you have any. Try to make your topic as descriptive as possible, so that it’s easier for people to help you!

local heat = 100
local maxHeat = 100
local touchingFire = false
local runService = game:GetService("RunService")
local workspace = game:GetService("Workspace")

local function updateHeatUI()
	script.Parent.Size = UDim2.new(math.clamp(heat / maxHeat, 0, 1), 0, 1, 0)
end

runService.Heartbeat:Connect(function(deltaTime)
	while heat > 0 do
		heat = heat - 1 * deltaTime
		updateHeatUI()
		local hrp = game.Players.LocalPlayer.Character.HumanoidRootPart
		if hrp then
			local parts = hrp:GetPartsInPart()
			for _, part in pairs(parts) do
				if part.Name == "FireBox" then
					touchingFire = true
					heat = heat + 1 * deltaTime
					updateHeatUI()
					break
				end
			end
		else
			touchingFire = false
		end
	end
end)
1 Like

You can try to change the pairs(parts) to be hrp:GetDecendants()

for _, part in hrp:GetDecendants() do

Hope this helps!

An error popped up, is there something wrong with the code in general?

 GetDecendants is not a valid member of Part "Workspace.fetviper_4.HumanoidRootPart"

where is the FireBox located inside of the player character model?

its not, its located in the workspace. there is intent for there to be multiple fireboxes.

So the code is trying to find the fire box part in the HumanoidRootPart instead of the Worksace where it actually is. So you might want to try and call it just using its path.

How do i get multiple fireboxes into this script, can’t i just check if the player is touching that part?

you might want to use a new script in the part itself that can detect a player and then update the UI and take away health (if thats what you want)

thats gonna be very hard to code, i’m not great at server-client connections. How do i check if the player’s character is touching ‘FireBox’ by getting everything that the player touches.

Checking every frame if the player is touching the firebox would be very performance costing. I recommend making an invisible uncollidable part that will act as a hitbox of the firebox and then having a script inside the firebox that will react to it being touched

Example script in the firebox:

local firebox = script.Parent
local hitbox: BasePart = firebox.Hitbox

local touchingPlayers = {}

function OnTouched(otherPart)
	-- Checking if the other part is a body part of a player
	if otherPart.Parent:FindFirstChildWhichIsA("Humanoid") then
		if not table.find(touchingPlayers, otherPart.Parent) then
			table.insert(touchingPlayers, otherPart.Parent)
		end
	end
end

function OnTouchEnded(otherPart)
	-- index is the position of the player in the table
	local index = table.find(touchingPlayers, otherPart.Parent)
	if index then
		local player = touchingPlayers[index]
		
		-- Check if any other body parts of the player is touching the hitbox
		local isPartOfPlayerInHitbox = false
		for _, part in hitbox:GetTouchingParts() do
			if part:IsDescendantOf(player) then
				isPartOfPlayerInHitbox = true
				break
			end
		end
		
		-- If player is not inside the hitbox, then remove him from the table 
		if not isPartOfPlayerInHitbox then
			table.remove(touchingPlayers, index)
			
			-- Lower the player's heat here
		end
		
	end
end


hitbox.TouchEnded:Connect(OnTouchEnded)
hitbox.Touched:Connect(OnTouched)

This is a rough script and it has much room for improvement so I don’t want you straight up copying it and putting it in your game. The links below will greatly help you with this.
Look up this CollectionService or watch this video explaining it

1 Like

try changing the line above to this

local parts = hrp:GetTouchingParts()

This should be; hrp:GetDescendants() or maybe you could use hrp:GetChildren()
Seems to be a slight spelling error there …

i have applied your code and it works! almost. the touchingfire value keeps getting clamped to true once it is set, even though isTouchingFire is set to false.

local script for heatbar gui

local heat = 100
local maxHeat = 100
local isTouchingFire = script.Parent.Parent.Parent.Parent.Parent.IsTouchingFire
local runService = game:GetService("RunService")
local workspace = game:GetService("Workspace")
local touchingFire = isTouchingFire.Value

local function updateHeatUI()
	script.Parent.Size = UDim2.new(math.clamp(heat / maxHeat, 0, 1), 0, 1, 0)
	print(heat .."/".. maxHeat)
	print(touchingFire)
end

runService.Heartbeat:Connect(function(deltaTime)
	touchingFire = isTouchingFire.Value
	if isTouchingFire.Value == true and math.round(heat) <= maxHeat then
		heat = heat + 2 * deltaTime
	elseif touchingFire ~= true and math.round(heat) >= 0 then
		heat = heat - 1 * deltaTime
	elseif heat > maxHeat then
		heat = heat - 1
	else
		heat = heat
	end
	updateHeatUI()
end)

script for firebox:

local firebox = script.Parent
local Players = game:GetService("Players")


local touchingPlayers = {}

function OnTouched(otherPart)
	-- Checking if the other part is a body part of a player
	if otherPart.Parent:FindFirstChildWhichIsA("Humanoid") then
		if not table.find(touchingPlayers, otherPart.Parent) then
			table.insert(touchingPlayers, otherPart.Parent)
			local player = Players:GetPlayerFromCharacter(otherPart.Parent)  -- get the player whose character is in the workspace
			local playerGui = player.PlayerGui
			playerGui.IsTouchingFire.Value = true
		end
	end
end

function OnTouchEnded(otherPart)
	-- index is the position of the player in the table
	local index = table.find(touchingPlayers, otherPart.Parent)
	if index then
		local player = touchingPlayers[index]

		-- Check if any other body parts of the player is touching the hitbox
		local isPartOfPlayerInHitbox = false
		for _, part in firebox:GetTouchingParts() do
			if part:IsDescendantOf(player) then
				isPartOfPlayerInHitbox = true
				break
			end
		end

		-- If player is not inside the hitbox, then remove him from the table 
		if not isPartOfPlayerInHitbox then
			local player = table.find(touchingPlayers, index)
			local playerGui = player.PlayerGui
			playerGui.IsTouchingFire.Value = false
			table.remove(touchingPlayers, index)
		
		end

	end
end


firebox.TouchEnded:Connect(OnTouchEnded)
firebox.Touched:Connect(OnTouched)

never use the “Touched” event because they do not guarantee accuracy. For example, if a player quickly runs out of the zone, the touchedEnded event will not be processed, and the player will heat up.

local plr = game:GetService('Player').LocalPlayer

local heat = 0
local MAX_HEAT = 100

local fireBox = workspace:WaitForChild(...)
local FireParams = OverlapParams.new()
FireParams.FilterType = Enum.RaycastFilterType.Include

plr.CharcterAdded:Connect(function(char)
  FireParams.FilterDescendantsInstances = {char}
  char.Changed:Connect(function()
    local Touching = fireBox:GetPartsInPart(FireParams)
    if Touching == {} then return end
    
    heat = math.clamp(heat+.05, 0, 1)
    script.Parent.Size = Udim2.fromScale(heat/MAX_HEAT, 0)
  end
end)

SORRY FOR THE LATE RESPONSE

Alright, new idea. Instead of checking if the firebox is touched, let’s check if the humanoid is touched.

Make a script in ServerScriptService and give every player an attribute called “Heat” and set it to 100 or the starting heat value. Since I see you’re setting player’s heat locally, which is very exploitable.

Server script:

local players = game:GetService("Players")

local playersNearFireBoxes = {}

function OnTouched(otherPart: BasePart, player)
	-- Checking if the other part is a source of heat
	if otherPart:HasTag("HeatSource") then
		if not table.find(playersNearFireBoxes, player) then
			table.insert(playersNearFireBoxes, player)
		end
	end
end

function OnTouchEnded(otherPart, player)
	-- index is the position of the player in the table
	local index = table.find(playersNearFireBoxes, player)
	local character = player.Character or player.CharacterAdded:Wait()
	local hrp : BasePart = character:WaitForChild("HumanoidRootPart")
	
	if otherPart:HasTag("HeatSource") then
		
		-- Checking if player is touching a different heat source
		local isTouchingAnotherSource = false
		for _, part in hrp:GetTouchingParts() do
			if part:HasTag("HeatSource") then
				isTouchingAnotherSource = true
				break
			end
		end
		
		if not isTouchingAnotherSource then
			table.remove(playersNearFireBoxes, index)
		end
	end
end

-- Setting up every player's heat counter
players.PlayerAdded:Connect(function(player)
	player:SetAttribute("Heat", 100)
	
	local character = player.Character or player.CharacterAdded:Wait()
	local hrp : BasePart = character:WaitForChild("HumanoidRootPart")
	
	-- Adding an extra argument "player" so the functions know what player it is
	hrp.Touched:Connect(OnTouched, player)
	hrp.TouchEnded:Connect(OnTouchEnded, player)
end)


-- A coroutine to manage all player's heat counters while not interrupting the rest of the script
coroutine.resume(coroutine.create(function()
	while true do
		for _, player in players:GetChildren() do
			if table.find(playersNearFireBoxes, player) then
				player:SetAttribute("Heat", player:GetAttribute("Heat") + 1)
			else
				player:SetAttribute("Heat", player:GetAttribute("Heat") - 1)
			end
		end
		task.wait(1)
	end
end))

In this script we are setting every player’s “Heat Counter” and whenever the player’s hrp touches a part, we will check if its a heat source and put him in a table. Whenever the hrp stops touching a part we will remove him from said table.

Give every hitbox the tag “HeatSource” and you’re set.

We will use the table to change every player’s heat counter accordingly. Now for the gui:

local player = game.Players.LocalPlayer

player.AttributeChanged:Connect(function(attribute)
	if attribute == "Heat" then
		
		local value = player:GetAttribute("Heat")
		
		-- Adjust the Ui accordingly
		
	end
end)

This will be a simple local script in the player scripts, or player gui, or wherever u want it. Instead of saving the heat value locally where its easily accessed by exploiters, the value is managed by the server and the player will only adjust the Ui, which wont cause any harm.

its okay, im changing paths and using events to help get the heat system to work. thanks for your help

1 Like

You can use the distance between the campfire and the player to get a percentage of how far the player is from the heat source. Then, multiply the amount of heat provided when standing near the campfire by this percentage

local heat = (1 - (fire.Position - Player.Position). Magnitude/ 20 ) * 5

it will be easier and more optimized.

  • realism

the problem is that the script runs every single heartbeat. so it would go down really quickly, plus the box allows me to place it within structures and mold it around them to make the structures warm.

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