Can I assign a tool handle to a different position?

I’ve been trying to make a tool that can be toggled between being held by the hand and being on the right waist of the player’s character, but i don’t know how to assign the tools position on the waist. can anyone help me out?

here’s a picture of what i want the tool to be like on the waist:

edit: this post i made is based on an idea i had on trying to make a tool similar to the Azure Periastron Alpha sword’s ability to be put on the players back and then back into the hand, but instead of on the back, it goes on the waist.

2 Likes

When a character equips a tool, there’s a weld created from their hand to the Handle. You can change the weld to change the Tool’s attachment.

If you don’t know how to use welds, the API reference is quite helpful, especially this snippet:

1 Like

after testing, ive created both a script and a localscript for changing the weld to the LowerTorso part of the character for both a dummy charater rig and a player character rig.

the script:

local tool = script.Parent.Parent
if tool.Parent == workspace.Dummy then
	workspace.Dummy.RightHand.RightGrip.Part0 = workspace.Dummy.LowerTorso
end

the localscript:

local tool = script.Parent.Parent
local plr = game.Players.LocalPlayer
local chara = plr.Character
local components = {
	righthand = chara:WaitForChild("RightHand",10),
}
if tool.Parent == chara then
	repeat wait() until components.righthand
	chara.RightHand.RightGrip.Part0 = chara.LowerTorso
end

all i have to find out is how to make it so that if you reequip it it attaches to the LowerTorso again, but now i want to know how to position it where i want it to and how to rotate it to the degrees i want it to be at.

1 Like

You can alter the rotation by using the C0 property of your weld assuming that Part1 is the tool and Part0 is the torso. Then you can use the CFrame.Angles( x, y, z ) method to rotate the tool (z, y, and z are in radians). I am not sure of how you want your tool rotated so you’ll have to mess with the values on your own. Helpful tip if you want to use degrees, use math.rad( degree ) to convert from degrees to radians.

As an example, you can do:

    weld.C0 = CFrame.new(xOffset, yOffset, zOffset) * CFrame.Angles(0, 0, math.rad(45)) --This would rotate the tool

For constantly setting the CFrame once equipped you can use the Tool.Equipped event of the Tool to reattach the tool. If your tool does not have a part named Handle or doesn’t need one make sure to uncheck the property named RequiresHandle or the Equipped event won’t fire.

3 Likes

i got the tool orientated and positioned where i want it, but now i want to do a toggle thing so that it toggles from being from the hand to being in the specified position.

1 Like

So you mean something such as pressing “e” would put the tool back onto your waist and if you press it again it would go back to your hand? If so, then you could just set Part0, assuming Part0 of the weld is the waist, to the character’s hand. Then you can again alter C0 to get the desired grab orientation and vice versa. If you are dealing with inputs such as keypresses look into the UserInputService. For setting the weld of the arm to be out in front as if you were holding a normal tool, you could either use an animation or weld the RightUpperArm, RightLowerArm, and RightHand to your desired weld positions and angles. To disable this “arm weld”, you could simply just set the Enabled property of the weld.

For example:

local Active = false

SomeToggleEvent:Connect(function() 
    if not Active then
        Active = true --Toggle
        
        --Hand
        weld.Part0 = RIGHT_HAND
        weld.C0 = CFrame.new(0, 0, 0) * CFrame.Angles(math.rad(45), 0, math.rad(45))

        --Enable Arm Weld
        RIGHT_UPPER_ARM_WELD.Enabled = true
        RIGHT_LOWER_ARM_WELD.Enabled = true
        RIGHT_HAND_WELD.Enabled = true

    else
        Active = false --Toggle
            
        --Waist
        weld.Part0 = LOWER_TORSO
        weld.C0 = CFrame.new(xOffset, yOffset, zOffset) * CFrame.Angles(0, 0, math.rad(45))
        
        --Disable Arm Weld
        RIGHT_UPPER_ARM_WELD.Enabled = false
        RIGHT_LOWER_ARM_WELD.Enabled = false
        RIGHT_HAND_WELD.Enabled = false
        
    end
end)

Tip: It’s generally a good idea to keep references (local instance = Some.Parth.To.A.Weld) to instances and only make them once if you need to reuse them a ton. Once not in use, you can simply set the Parent property to nil or disable it if it can be disabled, and if the instance is needed again simply re-set the parent property to the old parent or new parent.

Also, something I noticed in your script:

local components = {
	righthand = chara:WaitForChild("RightHand",10), --This waits until RightHand exists in the Character
}
if tool.Parent == chara then
	repeat wait() until components.righthand --The righthand should already exist since you did :WaitForChild() in the components table which was delcared before this if statement, so this is not needed.
	chara.RightHand.RightGrip.Part0 = chara.LowerTorso
end
1 Like

if i dont have the repeat untill it give the error RightGrip is not a valid member of MeshPart, so if i dont have it the script would break.
also, i think its now 100% percent ready, but im going to put the final version of the localscript on here to make sure no one says it doesn’t work in their opinion.

local tool = script.Parent.Parent
local plr = game.Players.LocalPlayer
local chara = plr.Character
local components = {
	righthand = chara:WaitForChild("RightHand"), --the weld
	waistOn = tool.Handle.Values.WaistOn --the boolvalue toggle
}
local function Equiped()
	components.waistOn.Value = false --on every equip it changes it to off
end


local function Activate()
	if components.waistOn.Value == true then 
		components.waistOn.Value = false
	else
		components.waistOn.Value = true	
	end
end


tool.Activated:Connect(Activate)
tool.Equipped:Connect(Equiped)

while true do
	repeat wait() until components.righthand
	if tool.Parent == chara then
		if components.waistOn.Value == true then
			chara.RightHand.RightGrip.Part0 = chara.LowerTorso
			chara.RightHand.RightGrip.C0 = CFrame.new(math.rad(65), math.rad(-30), math.rad(15)) * CFrame.Angles(math.rad(135), 0, 0)
		else
			chara.RightHand.RightGrip.Part0 = chara.RightHand
			chara.RightHand.RightGrip.C0 = CFrame.new(0, 0, 0) * CFrame.Angles(math.rad(-90), math.rad(-90), 0)
		end
	end
	wait()
end

thank y’all so much for the help!

1 Like

This is unneeded, you are constantly resetting the Weld.

while true do
	repeat wait() until components.righthand
	if tool.Parent == chara then
		if components.waistOn.Value == true then
			chara.RightHand.RightGrip.Part0 = chara.LowerTorso
			chara.RightHand.RightGrip.C0 = CFrame.new(math.rad(65), math.rad(-30), math.rad(15)) * CFrame.Angles(math.rad(135), 0, 0)
		else
			chara.RightHand.RightGrip.Part0 = chara.RightHand
			chara.RightHand.RightGrip.C0 = CFrame.new(0, 0, 0) * CFrame.Angles(math.rad(-90), math.rad(-90), 0)
		end
	end
	wait()
end

A better version would work as so:

local tool = script.Parent.Parent
local plr = game.Players.LocalPlayer
local chara = plr.Character

local rightGrip = chara:WaitForChild("RightHand"):WaitForChild("RightGrip") --the weld
local waistOn = false

--Is this used anywhere else? If not use a variable such as shown with waistOn
local waistOnBoolValue = tool.Handle.Values.WaistOn --the bool value toggle (Couldn't this be stored as a variable as shown?)


local function Equiped()
    waistOn = false --Default to false

    --Not sure if something else uses this so we keep this here
    waistOnBoolValue.Value = false
end


local function Activate()
    waistOn = not waistOn --Toggle

    --Notice how I am doing this in the activate function?
    --This is ran when the tool is activated instead of every 1/30th a second as with wait().
    if waistOn then 
        chara.RightHand.RightGrip.Part0 = chara.LowerTorso
	    chara.RightHand.RightGrip.C0 = CFrame.new(1.13, -0.52, 0.26) * CFrame.Angles(math.rad(135), 0, 0)
    else
        chara.RightHand.RightGrip.Part0 = chara.RightHand
	    chara.RightHand.RightGrip.C0 = CFrame.new(0, 0, 0) * CFrame.Angles(math.rad(-90), math.rad(-90), 0)
    end

    --By the way, doing CFrame.new(x, y, z) is actually creating a CFrame at location X, Y, Z
    --
    --So you can't apply a rotation here in your case of (math.rad(65), math.rad(-30), math.rad(15))
    --It is actually creating a new CFrame at position (1.13, -0.52, 0.26) relative to the weld's Part0
    --But, multiplying this cframe by CFrame.Angles(math.rad(135), 0, 0) will apply a rotation.
    --CFrame.Angles() is actually creating a blank CFrame with the rotation as provided, then
    --When you multiply this with your "position" CFrame (1.13, -0.52, 0.26), you are in a sense 
    --then applying the rotation to the CFrame at point (1.13, -0.52, 0.26)


   --Not sure if something else uses this so we keep this here
    waistOnBoolValue.Value = not components.waistOn.Value
end


tool.Activated:Connect(Activate)
tool.Equipped:Connect(Equiped)


--Did you know you can also do this? This is known as an anonymous function.
tool.Equipped:Connect(function() 
    isEquipped = false
end)

For more help with CFrames, please refer to Understanding CFrames

2 Likes

after reading several posts on the devforum and finding useful info, I want to find out if I can make the tool, when welded to the waist, to stop the toolnoneanim animation from playing, and when its welded back to the hand, I want the toolnoneanim animation to play again. so far I’ve only gotten nothing useful as there is an event function, AnimationPlayed that can determine if the animation is played, but I don’t want to use that. I want to stop/play the toolnoneanim animation Without the AnimationPlayed function. if anyone can give me info on that, I would appreciate it.

When loading an animation to an animation controller such as a humanoid you are then given an AnimationTrack. With this you can call :Stop() and :Play() if this is what you are asking for.

yes, but i want to do it in my toggle script so that when welded to the waist it makes it so that the player’s hand isnt held out, then when welded back to the hand it makes the player’s hand be held out, in which i know the ToolNoneAnim animation is what im looking at for doing this, but without the necessary eventfunction that checks if an animation is played on the character.

my point is, can i even pair the eventfunction with my toggle script? all i know is you need addition lines of code to do it, but an eventfunction activates when the desired event is triggered, and i dont know if i can use it if its looped. if i can, then i can use the eventfunction without problems. and if i cant, ill have to go through a whole heap of confusion in doing this

To toggle when a tool is held in the arm of your character or not, you can rename Handle into anything else (when character doesn’t need to hold the tool) and rename it back to Handle (character will hold it again). This doesn’t break the grip weld.
Also tool’s RequiresHandle must be false to do this.

@pewpie12302die i didnt even know you could do that. ill try it out later today!

1 Like

just tried it out. seems to work fine! all i had to do was add an unequipped function so that it would rename it to Handle, otherwise if it makes the name not Handle and you unequip it at the same time, reequipping it would make it fall out of the players hand. thank you for the info @pewpie12302die, as its more helpful then trying to find out if i can disable the hold out animation and enable it again.

thanks @viindicater, @Arkiuma, @anon66957764, and @pewpie12302die for helping me make this tool! it works perfectly now and i get no errors at all within the script! thanks again for yalls support!

2 Likes

i didnt even test it if it works with it being false, but the RequireHandle is set to true on the tool, and it works when renaming the handle. i dont know if you think it is needed but i didnt need to set the property to false.

I told you that because a tool with RequireHandle = true and without a Handle will not fire Tool.Equipped.

oh, i see your point. luckily, i have it set to where Tool.Equipped isnt a high priority, as all it does is set the BoolValue i have inside of the tool to False. but ya, i get what ya mean.