Help on my punch tool [RESOLVED]

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!
  2. I want to create finsher effects for my punch tool. (finishers are special effects on the players killing hit, like the player being flinged further or a special animation playing.)
  3. What is the issue? Include screenshots / videos if possible!
    Everything works fine, the finisher triggers, the smoke and vfx works on the finisher, its just the impact frames (black and white frames that appear on impact) are not working.
  4. What solutions have you tried so far?
    i have used print statements to check but it does not really make much sense.
    Server Script:
local Tool = script.Parent
local Remote = Tool:WaitForChild(“Remote”)
local Handle = Tool:WaitForChild(“Handle”)
local Mesh = Handle:WaitForChild(“Mesh”)

local Equipping = false
local Grip = nil

local StraightMeshData = “http://www.roblox.com/asset/?id=193827643”
local StraightGripPos = Vector3.new(0, 0, 1.5)
local BentMeshData = “http://www.roblox.com/asset/?id=193827593”
local BentGripPos = Vector3.new(0, 0.6, 0.5)
local Bent = true

local AttackAble = true
local AttackRestTime = 1
local AttackVictims = {}
local AttackDamage = 20
local AttackWindow = 0.66
local AttackDamaging = false
local AttackWindup = 0.1

local LowHealthThreshold = 7
local LowHealthSoundHit = Handle:WaitForChild(“finisherSoundHit”) – Add this sound to the Handle in Roblox Studio
local LowHealthSoundWind = Handle:WaitForChild(“finisherSoundWind”) – Add this sound to the Handle in Roblox Studio

function switchBend()
if Bent then
Mesh.MeshId = StraightMeshData
–Tool.GripPos = StraightGripPos
else
Mesh.MeshId = BentMeshData
–Tool.GripPos = BentGripPos
end
Bent = not Bent
end

function getPlayer()
local char = Tool.Parent
return game:GetService(“Players”):GetPlayerFromCharacter(char)
end

function contains(t, v)
for _, val in pairs(t) do
if val == v then
return true
end
end
return false
end

function tagHuman(human)
local tag = Instance.new(“ObjectValue”)
tag.Value = getPlayer()
tag.Name = “creator”
tag.Parent = human
game:GetService(“Debris”):AddItem(tag)
end

function convertGrip()
if Tool.Parent and Tool.Parent:FindFirstChild(“Right Arm”) then
local weld = Tool.Parent[“Right Arm”]:FindFirstChild(“RightGrip”)
if weld then
Grip = Instance.new(“Motor6D”)
Grip.Name = “RightGrip”
Grip.Part0 = weld.Part0
Grip.Part1 = weld.Part1
Grip.C0 = weld.C0
Grip.C1 = weld.C1
Grip.Parent = weld.Parent
weld:Destroy()
end
end
end

function normal()
if not AttackAble then return end

--rest
AttackAble = false
delay(AttackRestTime, function()
	AttackAble = true
end)

--damage
delay(AttackWindup, function()
	AttackVictims = {}
	AttackDamaging = true
	delay(AttackWindow, function()
		AttackDamaging = false
	end)
end)

--sound
Handle.Swing.Pitch = math.random(90, 110)/100
Handle.Swing:Play()

Handle.Hit.Volume = 0
Handle.Hit:Play()

--animation
switchBend()
delay(0.66, function()
	switchBend()
end)
Remote:FireClient(getPlayer(), "PlayAnimation", "Swing1")
end

function shove(char, strongerShove)
local wielder = Tool.Parent
if wielder and wielder:FindFirstChild(“HumanoidRootPart”) and char and char:FindFirstChild(“HumanoidRootPart”) then
local shover = wielder.HumanoidRootPart
local shovee = char.HumanoidRootPart

	local distance = strongerShove and 20 or 10
	local duration = 0.15
	local speed = distance/duration

	local velocity = (shovee.Position - shover.Position).unit * speed

	local shoveForce = Instance.new("BodyVelocity")
	shoveForce.maxForce = Vector3.new(1e9, 1e9, 1e9)
	shoveForce.velocity = velocity
	shoveForce.Parent = shovee
	game:GetService("Debris"):AddItem(shoveForce, duration)

	Handle.Hit.Volume = strongerShove and 1 or 0.5
	local fx = Handle.hitFx:Clone()
	fx.Parent = shovee.Parent.Torso
	fx:Emit()
	char.IsRagdoll.Value = true
	wait(1.5)
	char.IsRagdoll.Value = false
end
end

function onHandleTouched(part)
if not AttackDamaging then return end
if part:IsDescendantOf(Tool.Parent) then return end

if part.Parent and part.Parent:FindFirstChild("Humanoid") then
	local human = part.Parent.Humanoid
	if not contains(AttackVictims, human) then
		table.insert(AttackVictims, human)
		tagHuman(human)
		human:TakeDamage(AttackDamage)

		if human.Health <= LowHealthThreshold then
			LowHealthSoundHit:Play()
			LowHealthSoundWind:Play()
			Handle.power.Brightness = 40
			Handle.FIRE:Emit()
			Handle.GLOW:Emit()
			Handle.SPECKS:Emit()
			
			wait(0.1)
			Handle.power.Brightness = 0
			Tool.impactframeTrigger:FireClient(game:GetService("Players"):GetPlayerFromCharacter(Tool.Parent), human)
			print("sent fire impact frame")
			shove(part.Parent, true) -- Stronger shove
		else
			shove(part.Parent, false)
		end
	end
end
end

function onEquip()
if Equipping then return end
Equipping = true

convertGrip()

--animation
Remote:FireClient(getPlayer(), "PlayAnimation", "Idle")

Equipping = false
end

function onUnequip()
if Grip then
Grip:Destroy()
end

--animation
Remote:FireClient(getPlayer(), "StopAnimation", "Idle")
end

function onRemote(player, func, …)
if player ~= getPlayer() then return end

if func == "NormalStart" then
	normal()
end
end

Tool.Equipped:connect(onEquip)
Tool.Unequipped:connect(onUnequip)
Remote.OnServerEvent:connect(onRemote)
Handle.Touched:connect(onHandleTouched)

Client Script:

local Player = game:GetService(“Players”).LocalPlayer
local UIS = game:GetService(“UserInputService”)
local Tool = script.Parent
local Remote = Tool:WaitForChild(“Remote”)
local Tracks = {}
local InputType = Enum.UserInputType

– Helper function to play an animation
function playAnimation(animName, …)
if Tracks[animName] then
Tracks[animName]:Play()
else
local anim = Tool:FindFirstChild(animName)
if anim and Tool.Parent and Tool.Parent:FindFirstChild(“Humanoid”) then
Tracks[animName] = Tool.Parent.Humanoid:LoadAnimation(anim)
playAnimation(animName, …)
end
end
end

– Helper function to stop an animation
function stopAnimation(animName)
if Tracks[animName] then
Tracks[animName]:Stop()
end
end

– Function to handle tool activation (both for desktop and mobile)
function onActivated()
Remote:FireServer(“NormalStart”)
end

– Function to handle tool deactivation (for when the action stops)
function onDeactivated()
Remote:FireServer(“NormalStop”)
end

– Function to handle remote events
function onRemote(func, …)
if func == “PlayAnimation” then
playAnimation(…)
elseif func == “StopAnimation” then
stopAnimation(…)
end
end

– Connect the tool’s activation and deactivation events
Tool.Activated:Connect(onActivated)
Tool.Deactivated:Connect(onDeactivated)

– Connect remote events
Remote.OnClientEvent:Connect(onRemote)

Impact Frame Script:

script.Parent.impactframeTrigger.OnClientEvent:Connect(function(player, human)
print(“impact frame triggered”)
local playerCam = game.Workspace.CurrentCamera
local highFX1 = Instance.new(“Highlight”)
highFX1.Name = “highFX1”
highFX1.FillTransparency = 0
highFX1.FillColor = Color3.new(0,0,0)
highFX1.Parent = player.Character
local highFX2 = Instance.new(“Highlight”)
highFX1.Name = “highFX1”
highFX1.FillTransparency = 0
highFX1.FillColor = Color3.new(0,0,0)
highFX1.Parent = human.Parent
local impactFrame1 = Instance.new(“ColorCorrectionEffect”)
impactFrame1.Name = “impactFrame1”
impactFrame1.Brightness = 1
impactFrame1.Parent = playerCam
wait(0.25)
print(“changing impact frames”)
local tarHighFX1 = player.Character.highFX1
local tarHighFX2 = human.Parent.highFX2
local tarImpactFrame = playerCam.impactFrame1
tarHighFX1.FillColor = Color3.new(1,1,1)
tarImpactFrame.Brightness = -1
wait(0.25)
print(“destroying impact frames”)
tarHighFX1:Destroy()
tarHighFX2:Destroy()
tarImpactFrame:Destroy()
end)

Tool Layout:
Screenshot 2024-08-20 at 8.18.17 PM

1 Like

The highFX2 is exactly same as highFX1. Seems like you forgot to change things after copy paste.
(For love of everything, use indentation and spaces, will make everybody’s life easier)

Hi thanks for the reply, I will try that out but the reason there are 2 highFX’s are because I want 2 focus contrast points, the character of the puncher and the character of the victim. Meaning that for a split second of the impact, the screen will turn white except for the black fill on the puncher and the victim and then it will invert the colors and disappear. I guess I could have made it more simple by just cloning it twice and parenting them to different characters, but I don’t think that would affect the functionality of the script, because the impact frames aren’t appearing AT ALL. I will send a video later of me using it and the error messages

Just realized that you are using highlights. Try setting the Adornee parameter to the part/model. This is possible issue, why they don’t appear.

Thanks, I will definitely try that, but there isn’t only highlights, there’s also a color correction effect being placed in the game.Workspace.CurrentCamera, and I can’t see that either, my only guess is that the remote event values aren’t being passed properly, as I’m not very good with RemoteEvents, but to me the remote events look like they are working properly, so maybe I will try to get better at remote events.

is the output on impact frame worked?

if not it is better to put the event on ReplicatedStorage putting it in the tool is very risky as it is not working everytime

this post will be closed as while rewriting the code i found a better way to do it and it worked. thanks everyone for helping and i will mark the first person as solution as thanks.

1 Like

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