Spatial Query Punching Tool

Im trying to make a fist tool using spatial query to detect players hit but I wanna make it accurate so I use keyframeReached to make sure that the player doesnt hit someone in a different keyframe. Now that im thinking maybe i should just get the parts at the last keyframe which may be better, where the fist extends out.

Sometiemes the fists does a single damage to the character but then sometimes it damages the player 2-4 times in one punch, and im not sure why it is doing this

-- local function onToolActivated()
	if not loadAnimationTracks() then return end
	
	currentTime = time(); if currentTime - lastTime <= 2.5 then return end
	
	local overlapParams = OverlapParams.new()
	overlapParams.FilterType = Enum.RaycastFilterType.Exclude
	overlapParams.FilterDescendantsInstances = {character}
	
	local track = alternateHands and leftAnimationTrack or rightAnimationTrack
	
	local playersHit = {}

	local reference = {
		[leftAnimationTrack] = character.LeftHand,
		[rightAnimationTrack] = character.RightHand
	}
	
	local damageDealtToPlayers = {}  -- Table to track damage dealt to players

	track.KeyframeReached:Connect(function()
		local queryResult = workspace:GetPartsInPart(reference[track], overlapParams)

		for _, part in pairs(queryResult) do
			local humanoid = part and part.Parent and part.Parent:FindFirstChildOfClass("Humanoid")

			if humanoid then
				if not damageDealtToPlayers[part.Parent] then
					damageDealtToPlayers[part.Parent] = true

					if not table.find(overlapParams.FilterDescendantsInstances, part.Parent) then
						overlapParams:AddToFilter(part.Parent)
					end

					--print("Did Damage:", humanoid.Health, " Time: ", currentTime - lastTime)

					print(part.Parent)

					humanoid:TakeDamage(10)
				end
			end
			task.wait()
		end
	end)
	
	track:Play()
	
	alternateHands = not alternateHands
	lastTime = time()
	damageDealtToPlayers = {}
end

3 Likes

This is because you are connecting to track.KeyframeReached every time you play the animation. Instead, connect outside of the onToolActivated() function and reset damageDealtToPlayers every time you punch. Try this:

local damageDealtToPlayers = {}  -- Table to track damage dealt to players
local reference = {
	[leftAnimationTrack] = character.LeftHand,
	[rightAnimationTrack] = character.RightHand
}
local overlapParams = OverlapParams.new()

local function onToolActivated()
	if not loadAnimationTracks() then return end
	
	currentTime = time(); if currentTime - lastTime <= 2.5 then return end
	
	overlapParams.FilterType = Enum.RaycastFilterType.Exclude
	overlapParams.FilterDescendantsInstances = {character}
	
	local track = alternateHands and leftAnimationTrack or rightAnimationTrack
	damageDealtToPlayers = {}

	track:Play()
	
	alternateHands = not alternateHands
	lastTime = time()
end

local function onKeyFrameReached()
		local queryResult = workspace:GetPartsInPart(reference[track], overlapParams)

		for _, part in pairs(queryResult) do
			local humanoid = part and part.Parent and part.Parent:FindFirstChildOfClass("Humanoid")

			if humanoid then
				if not damageDealtToPlayers[part.Parent] then
					damageDealtToPlayers[part.Parent] = true

					--print("Did Damage:", humanoid.Health, " Time: ", currentTime - lastTime)

					print(part.Parent)

					humanoid:TakeDamage(10)
				end
			end
			task.wait()
		end
end)

leftAnimationTrack.KeyframeReached:Connect(onKeyFrameReached)
rightAnimationTrack.KeyframeReached:Connect(onKeyFrameReached)

1 Like

How do i initialize left and right animation track at the start of the script? otherwise its just saying attempt to index .KeyframeReached from nil

1 Like

Ok so I just did this and ye it seems to be working fine when moving it outside of the activated, I think it might be because maybe the connection is running many times maybe when I click my mouse multiples times they are running all the same time.

local player = Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local animator = character:WaitForChild("Humanoid") and character:WaitForChild("Humanoid").Animator

local tool = script.Parent

local rightAnimationTrack = animator and animator:LoadAnimation(tool.Animations.RightPunch)
local leftAnimationTrack = animator and animator:LoadAnimation(tool.Animations.LeftPunch)
1 Like

exactly, you only need to have one connection active

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