I know I already made 2 topics about ViewModels, but now I have it working how I wanted it to work. Also I have one last issue which has me stuck. I have got the ViewModel to sway like a FPS, but the ViewModel is floating in the air. I’m also using EgoMoose’s FPS tutorial system
local humanoid = game.Players.LocalPlayer.CharacterAdded:Wait():WaitForChild("Humanoid");
local hrp = game.Players.LocalPlayer.Character:WaitForChild("HumanoidRootPart");
local remoteEvents = game.ReplicatedStorage:WaitForChild("RemoteEvents");
local viewModel = game.ReplicatedStorage:WaitForChild("viewModel"):Clone();
local repWeapon = game.ReplicatedStorage:WaitForChild("M249");
local weapon = repWeapon:Clone();
-- setup
weapon.Parent = viewModel;
viewModel.Parent = camera;
local joint = Instance.new("Motor6D");
joint.C0 = CFrame.new(1, -1.5, -2);
joint.Part0 = viewModel.Head;
joint.Part1 = weapon.Handle;
joint.Parent = viewModel.Head;
local aimCount = 0;
local offset = weapon.Handle.CFrame:inverse() * weapon.Aim.CFrame;
remoteEvents.setup:FireServer(repWeapon);
wait();
local holdAnim = humanoid:LoadAnimation(repWeapon.HoldAnim);
local aimAnim = humanoid:LoadAnimation(repWeapon.AimAnim);
local lastAnim = holdAnim;
lastAnim:Play();
-- functions
local function updateArm(key)
local shoulder = viewModel[key.."UpperAr"][key.."Shoulder"];
local cf = weapon[key].CFrame * CFrame.Angles(math.pi/2, 0, 0) * CFrame.new(0, 1.5, 0);
shoulder.C1 = cf:inverse() * shoulder.Part0.CFrame * shoulder.C0;
end
local function aimDownSights(aiming)
local start = joint.C1;
local goal = aiming and joint.C0 * offset or CFrame.new();
lastAnim:Stop();
lastAnim = aiming and aimAnim or holdAnim;
lastAnim:Play();
aimCount = aimCount + 1;
local current = aimCount;
for t = 0, 101, 10 do
if (current ~= aimCount) then break; end
game:GetService("RunService").RenderStepped:Wait();
joint.C1 = start:Lerp(goal, t/100);
end
end
-- events
local function onDied()
viewModel.Parent = nil;
end
local function onUpdate(dt)
viewModel.Head.CFrame = camera.CFrame;
updateArm("Right");
updateArm("Left");
end
local function onInputBegan(input, process)
if (process) then return; end
if (input.UserInputType == Enum.UserInputType.MouseButton2) then
aimDownSights(true);
end
end
local function onInputEnded(input, process)
if (process) then return; end
if (input.UserInputType == Enum.UserInputType.MouseButton2) then
aimDownSights(false);
end
end
local runcf = camera.CFrame;
local function sprint(actionName, inputState, inputObject)
if inputState == Enum.UserInputState.Begin then
runcf = runcf:lerp(CFrame.new() * CFrame.Angles(math.rad(-20),math.rad(20),math.rad(20)),.1)
game.Players.LocalPlayer.Character.Humanoid.WalkSpeed = 20
else
runcf = runcf:lerp(CFrame.new(),.1)
game.Players.LocalPlayer.Character.Humanoid.WalkSpeed = 16
end
end
local walkanimcf = joint.C0; -- the start of issue
game:GetService("RunService").RenderStepped:Connect(function()
viewModel:SetPrimaryPartCFrame( -- I have Head as PrimaryPart
walkanimcf
)
end)
game:GetService("RunService").RenderStepped:Connect(function()
local speed = game.Players.LocalPlayer.Character.Humanoid.WalkSpeed/16
walkanimcf = walkanimcf:lerp(
CFrame.Angles(
0,
0,
-.02 * math.sin(tick() * (2 * speed))
)
,.5)
end) -- the end of issue
-- connections
humanoid.Died:Connect(onDied);
game:GetService("RunService").RenderStepped:Connect(onUpdate);
game:GetService("UserInputService").InputBegan:Connect(onInputBegan);
game:GetService("UserInputService").InputEnded:Connect(onInputEnded);
game:GetService("ContextActionService"):BindAction("Run", sprint, true, Enum.KeyCode.LeftShift)
while (true) do
wait(0.1);
remoteEvents.tiltAt:FireServer(math.asin(camera.CFrame.LookVector.y));
end```