This script fires in the air when I'm trying to only make it fire when the player is touching anything BUT air

So this question is straight forward, I want this script to print out something when the player isn’t touching the air, however it prints out whenever the player is touching anything at all. How can I fix this?

Script:

local character = script.Parent 
local humanoid = character:WaitForChild("Humanoid")
local fatality = {
	["Head"] = "Very Fatal",
	["Torso"] = "Fatal",
	["Left Arm"] = "Moderate",
	["Right Arm"] = "Moderate",
	["Left Leg"] = "Ok",
	["Right Leg"] = "Ok"
}

humanoid.StateChanged:Connect(function(oldState, newState)
	if newState == Enum.HumanoidStateType.Freefall or newState == Enum.HumanoidStateType.Landed then
		for i, v in pairs(character:GetDescendants()) do
			if v:IsA("BasePart") then
				v.Touched:Connect(function(hit)
					local startCollision = tick()
					v.TouchEnded:Connect(function()
						local endCollision = tick()
						if startCollision and endCollision ~= nil then
							if endCollision - startCollision <= 0.5 then
								local random = math.random(1, 2)
								if random == 1 then -- Cut
									for BP, Severity in pairs(fatality) do
										if hit.Material == Enum.Material.Air then
											continue
										end
										if v.Name == BP then
											print("Cut, "..v.Name..", "..Severity)
										end
									end
								elseif random == 2 then -- Bruise
									for BP, Severity in pairs(fatality) do
										if hit.Material == Enum.Material.Air then
											continue
										end
										if v.Name == BP then
											print("Bruise,"..v.Name..", "..Severity)
										end
									end
								end
							elseif endCollision - startCollision >= 0.5 then -- scrape
								for BP, Severity in pairs(fatality) do
									if hit.Material == Enum.Material.Air then
										continue
									end
									if v.Name == BP then
										print("Scrape, "..v.Name..", "..Severity)
									end
								end
							end
						end
					end)
				end)
			end
		end
	end
end)

isn’t this the issue? the state “landed” only lasts for a brief moment when the player makes contact on the ground after the “freefall” state

so should i remove it and just only detect if they landed? if so is there an alternative to check they got hit WHILE falling, but it has to be anything other than air

yes, “landed” is when they make contact on the ground

wouldn’t print anything even if you hit the ground

https://developer.roblox.com/en-us/api-reference/property/Humanoid/FloorMaterial

Reading from Humanoid.FloorMaterial is going to be a good bet for determining whether a Humanoid is grounded or not; but there’s a few other problems in your code. Enum.Material.Air is used to represent the empty space we perceive as “air”. It is not a real material that can be normally applied to parts, and you don’t need to check if a part’s material is air.

You’re also connecting a function to Part.Touched every time the humanoid state changes to Freefall or Landed, and never disconnecting those functions.

There’s a bunch of duplicate code as well, and it makes debugging more of a nightmare than it has to be.

1 Like

If newState == Enum.HumanoidStateType.Freefall then print(“in air”)

or just inside whichever function you want just

print(Enum.HumanoidStateType)

to let you know what the actual StateType is during the script.

So what should I do to fix them?

can i use thiw for other humanoidstatetypes for example ragdoll or fallingdown?

right right i forgot to mention that but since i have time now

since state types, floor material or even possible raycast may not be efficient against detecting impacts, you can try to instead get the linear velocity of the character then run a loop that checks if the velocity is going at a constant flow to either positive or negative, if it does revert to a lower number (let’s say it’s going through a constant 130 in positive acceleration and it suddenly goes lower than 130 or another example is decelerating -30 (going more negative) and suddenly increases by a positive amount, it should count as a form of pause or impact) it will trigger the bruises as you have coded

for the severity of the pause, you can either get the difference in value between the previous velocity and the velocity after impact and multiply it for a certain result (that may either if low, have low fatality or vice versa)