Help needed getting the player's arms in the direction of a nearby target to hit them with a sword

How would I make the player’s hands go in the direction of the closest target to hit them with the sword using IK? I’ve never actually used IK before, but I have some understanding of what it can do.

If anybody could help me make this and maybe tell me how it works, that would be much appreciated.

I tried to make the code below as neat as possible

Things you need to know about my script:

  • The script is on the server and is located in StarterCharacterScripts
  • I’m using the RaycastHitbox module created by @TeamSwordphin
  • The RaycastHitbox module is located in the ReplicatedStorage
-- [[ Character ]] --
local Character = script.Parent
local Humanoid = Character:WaitForChild("Humanoid")

-- [[ Services ]] --
local Debris = game:GetService("Debris")
local TweenService = game:GetService("TweenService")
local Workspace = game:GetService("Workspace")
local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

-- [[ Objects ]] --
local FX_Folder = Workspace:WaitForChild("FX")
local ServerAssets = ServerStorage:WaitForChild("ServerAssets")
local SlashEffect = ServerAssets:WaitForChild("Slash")

-- [[ Modules ]] --
local RaycastHitbox = require(ReplicatedStorage:WaitForChild("RaycastHitboxV3"))

-- [[ Boolean ]] --
local Debounce = false

-- [[ Tables ]] --
local Animations = {
	5860750701;
	5860755185;
	5860756987;
}

-- [[ Events ]] --
Character.ChildAdded:Connect(function(chil)
	if chil:IsA("Tool") then
		
		local Handle = chil:WaitForChild("Handle")
		local Hitbox = RaycastHitbox:Initialize(Character, {Character})
		
		Hitbox.OnHit:Connect(function(hit, humanoid)
			if humanoid.Health <= 0 then return end
			
			humanoid:TakeDamage(10)
			
			if hit.Name:match("Torso") or hit == hit.Parent.PrimaryPart then
				local Arms = {
					["RightUpperArm"] = 25;
					["RightLowerArm"] = 25;
					["LeftUpperArm"] = 25;
					["LeftLowerArm"] = 25;
				}
				
				local total = 0
				for _, Chance in next, Arms do
					total+=Chance
				end
				
				local value = math.random(0,total)
				
				for i, Chance in next, Arms do
					value-=Chance
					if value <= .01 then
						hit = hit.Parent[i]
						break
					end
				end
			end
			
			local directions = {"25","-25","50","-50"}
			local effect = SlashEffect:clone()
			effect.BrickColor = BrickColor.new("Terra Cotta")
			effect.Material = Enum.Material.Neon
			effect.Transparency = .6
			effect.CanCollide = false
			effect.Anchored = true
			effect.CFrame = hit.CFrame * CFrame.new(
				 math.random(10,20)/10,
				 math.random(10,20)/10,
				-math.random(10,20)/10
			)
			
			effect.CFrame = hit.CFrame * CFrame.Angles(
				0,
				math.ceil(Character.PrimaryPart.Orientation.Y*90*math.pi^2),
				math.rad(tonumber(directions[math.random(1,#directions)]))
			)
			
			effect.Parent = FX_Folder
			
			local Info = TweenInfo.new(
				1,
				Enum.EasingStyle.Linear,
				Enum.EasingDirection.Out,
				0,
				false,
				.2
			)
			
			local Tween = TweenService:Create(effect, Info, {Transparency = 1})
			Tween:Play()
			Debris:AddItem(Info.Time, effect)
		end)
		
		chil.Activated:Connect(function()
			
			local Acceptable = chil.Parent == Character and not Debounce
			if Acceptable then
				
				Debounce = true
				
				Hitbox:HitStart()
				
				local Swing_Audio = Handle:FindFirstChild("Swing_Audio") or Instance.new("Sound")
				Swing_Audio.Parent = Handle
				Swing_Audio.Name = "Swing_Audio"
				Swing_Audio.Volume = .5
				Swing_Audio.SoundId = "rbxassetid://1306070008"
				Swing_Audio:Play()
				
				local Animation = Instance.new("Animation")
				Animation.AnimationId = ("rbxassetid://%d"):format(tostring(Animations[math.random(1, #Animations)]))
				local AnimationTrack = Humanoid:LoadAnimation(Animation)
				AnimationTrack:Play()
				
				local function Stop(time)
					wait(time)
					Hitbox:HitStop()
					Animation:remove()
					AnimationTrack:remove()
					Debounce = false
				end
				
				local thread = coroutine.wrap(Stop)
				thread(AnimationTrack.Length)
				
			end
			
		end)
	end
end)
1 Like