Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
0

Character and arms following player's mouse?

Asked by 4 years ago
local tool = script.Parent.Parent
local service = game:GetService("RunService") --get  run time servise

local success = false

local player = game:GetService("Players").LocalPlayer --get the current player
local character = player.Character or player.CharacterAdded:wait() --get character
local humanoid = character:WaitForChild("Humanoid") --get humanoid

local camera = game.Workspace.CurrentCamera --player camera
local mouse = player:GetMouse() --player mouse

local offset, magnitude, vector3, cFrame, direcction = nil --varibles to make calculations
local shoulder, arm, torso, body, neck = nil --variables to hold body parts
local defaultNeckCO, defaultShoulderCO = nil --variables to hold the defauld posicion of the body parts
local animate = nil --variable to hold the function of the animation

local shoulderPositionC0, shoulderCFramePositionC1 = nil --variables to extrack some data from the body parts
local turnAngle = CFrame.fromEulerAnglesXYZ(math.pi/2, 0, 0) --constant, used later on to make calculations
local rightangle = CFrame.fromEulerAnglesXYZ(0, 0, math.pi) --constant, used later on to make calculations

local unequipListener --listener to disconect the unequip function

--get offset
function updateOffset()
    offset = (body.Position.y - mouse.Hit.p.y) / 100
    magnitude = (body.Position - mouse.Hit.p).magnitude / 80
    return offset/magnitude
end

--get vector3 of direccion
function updateBodyRotation()

    if (camera.Focus.p - camera.CoordinateFrame.p).magnitude > 1 then
        --stop the defauld rotation
        humanoid.AutoRotate = false

        --get the rotation vector3
        vector3 = Vector3.new(mouse.Hit.p.x, body.Position.y, mouse.Hit.p.z)

        --create the cframe with the same posicion of the body and the new rotation
        cFrame = CFrame.new(body.Position, vector3)

        --updating the body rotation
        body.CFrame = cFrame
    else
        --get the defauld rotation
        humanoid.AutoRotate = true
    end

end

--function to animate the humanoid R15
function animateR15()
    --update neck
    offset = updateOffset()
    neck.C0 = defaultNeckCO * CFrame.fromEulerAnglesXYZ(-offset, 0, 0)

    --update arm
    vector3 = (torso.CFrame * CFrame.new(shoulderPositionC0)).p + Vector3.new(0, -0.25,0) --offset position
    direcction = (vector3 - mouse.Hit.p).unit 
    arm.CFrame = CFrame.new(vector3, vector3 + direcction) * turnAngle * shoulderCFramePositionC1 * rightangle 

    --NOTE: the following changes update the arm in a lesser accurate way, but it's faster,
    --to change the faster way, must comments the previous update arm (previus 3 code lines),
    --and add the following code line in the "getBodyParts()" in the R15 side
    --defaultShoulderCO  = CFrame.new(1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1)
    --then uncomment the following code line
    --shoulder.C0 = defaultShoulderCO * CFrame.fromEulerAnglesXYZ(-offset, 0, 0)
    --at last, the shoulder.C0 take some changes in the animation,
    --the defauld posicion have to by reset in defauld on "stopAllFunctions()", with the following code line:
    --shoulder.C0 = defaultShoulderCO
end

--function to animate the humanoid R6
function animateR6()
    --getting the offset
    offset = updateOffset()

    --update neck and arm, NOTE: this is almost the only variation between R6 nd R15,
    --and basically it's where is going to be the offset
    neck.C0 = defaultNeckCO * CFrame.fromEulerAnglesXYZ(offset, 0, 0)
    shoulder.C0 = defaultShoulderCO * CFrame.fromEulerAnglesXYZ(0, 0, -offset)
end

--function to get parts of the body depending on the humanoid
function getBodyParts()

    --same body in both humanoids types
    body = character.HumanoidRootPart

    --bifurcate between diferents humanoids to get part of the body
    if humanoid.RigType == Enum.HumanoidRigType.R15 then
        --R15

        --getting body parts
        shoulder = character.RightUpperArm.RightShoulder
        arm = character.RightUpperArm
        neck = character.Head.Neck
        torso = character.UpperTorso

        --deatach the arm
        arm.Anchored = true
        shoulder.Part1 = nil

        --setting animation
        animate = animateR15

        --Note: those CFrame are the defauld position of each motor6d
        defaultNeckCO = CFrame.new(0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1)
        shoulderCFramePositionC1 = CFrame.new(shoulder.C1.p)
        shoulderPositionC0 = shoulder.C0.p
    else
        --R6

        --getting body parts
        shoulder = character.Torso["Right Shoulder"]
        arm = character["Right Arm"] 
        neck = character.Torso.Neck

        --setting animation
        animate = animateR6

        --Note: those CFrame are the defauld position of each motor6d
        defaultNeckCO = CFrame.new(0, 1, 0, -1, -0, -0, 0, 0, 1, 0, 1, 0)
        defaultShoulderCO = CFrame.new(1, 0.5, 0, 0, 0, 1, 0, 1, 0, -1, -0, -0)
    end

end


--this function try to stop all function of this script and set defauld values
function stopAllFunctions()

    pcall(function()
        --disconect the unequip tool listener
        unequipListener:Disconnect()
    end)

    pcall(function()
        --stop the rendering of the animation
        service:UnbindFromRenderStep(script.Name)
    end)

    pcall(function()
        --reset defauld position of the neck 
        neck.C0 = defaultNeckCO
    end)

    pcall(function()
        --reset the defauld rotation of the body
        humanoid.AutoRotate = true
    end)

    pcall(function ()
        if humanoid.RigType == Enum.HumanoidRigType.R15 then
            --R15 
            --atach the arm
            shoulder.Part1 = arm
            arm.Anchored = false
        else
            --R6
            --reset defauld position of the arm 
            shoulder.C0 = defaultShoulderCO
        end
    end)

end

--function to animate the character
function characterFollowTool()

    --try to render the animation
    success = pcall(function()
        --update the Bogy rotation and offset
        updateBodyRotation()

        --execute the animation, this function it's diferent depending of the humanoid type
        animate()
    end)

    --if the rendering went wrong, 
    if not success then
        stopAllFunctions()
    end

end

function onEquip()
    --add listener to the tool to stop all functions when the tool is unequipped  
    unequipListener = tool.Unequipped:connect(stopAllFunctions)

    --getting the parts of the current character
    success = pcall(getBodyParts)
    if not success then
        stopAllFunctions()
    end

    --adding the animation in the rendering of the screen
    service:BindToRenderStep(script.Name, Enum.RenderPriority.Input.Value - 1, characterFollowTool)
end

tool.Equipped:connect(onEquip)

There a script i found in toolbox. I dont know how to make the same movement but with left arm. This script only moves head, torso and right arm.

1 answer

Log in to vote
0
Answered by 4 years ago

you don't need to move body parts one by one, that is wrong. Instead, all you need to do is pointing your HumanoidRootPart CFrame to your mouse direction

Character.PrimaryPart.CFrame = CFrame.new(Character.PrimaryPart.Position, mouse.Hit.P)
Ad

Answer this question