Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- -- @CloneTrooper1019, 2015
- -- Viewmodel script
- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- local c = workspace.CurrentCamera
- local rs = game:GetService("RunService")
- local player = game.Players.LocalPlayer
- local char = player.Character or player.CharacterAdded:wait()
- local charTorso = char:WaitForChild("Torso")
- local charHead = char:WaitForChild("Head")
- local root = char:WaitForChild("HumanoidRootPart")
- local rootJ = root:WaitForChild("RootJoint")
- local lhip = charTorso:WaitForChild("Left Hip")
- local rhip = charTorso:WaitForChild("Right Hip")
- local neck = charTorso:WaitForChild("Neck")
- local humanoid = char:WaitForChild("Humanoid")
- local origins = {}
- local factors = {}
- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- -- Torso Kinematics
- local function recordOrigins(...)
- for _,joint in pairs{...} do
- origins[joint] = { C0 = joint.C0, C1 = joint.C1 }
- end
- end
- local function onCharAdded(char)
- -- Set variables
- humanoid = char:WaitForChild("Humanoid")
- charTorso = char:WaitForChild("Torso")
- root = char:WaitForChild("HumanoidRootPart")
- rootJ = root:WaitForChild("RootJoint")
- lhip = charTorso:WaitForChild("Left Hip")
- rhip = charTorso:WaitForChild("Right Hip")
- neck = charTorso:WaitForChild("Neck")
- -- Setup custom rig.
- origins = {}
- recordOrigins(rootJ,lhip,rhip,neck)
- factors =
- {
- [rootJ] = Vector3.new(-.4,0,0);
- [lhip] = Vector3.new(0,0,.4);
- [rhip] = Vector3.new(0,0,-.4);
- [neck] = Vector3.new(-1.17,0,0);
- }
- end
- local function updateHip()
- if factors then
- local look = c.CoordinateFrame.lookVector.y
- for joint,factor in pairs(factors) do
- local origin = origins[joint]
- local factor = factor * look
- local x,y,z = factor.X, factor.Y, factor.Z
- joint.C0 = origin.C0 * CFrame.Angles(x,y,z)
- end
- end
- end
- if player.Character then
- onCharAdded(player.Character)
- end
- player.CharacterAdded:connect(onCharAdded)
- rs.RenderStepped:connect(updateHip)
- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- -- View Bobbling
- local waveScale = 0
- local scaleIncrement = 0.05
- local offStates = {"Jumping","PlatformStanding","Ragdoll","Seated","FallingDown","FreeFalling","GettingUp","Swimming"}
- local onStates = {"Running","Climbing"}
- for _,state in pairs(offStates) do
- humanoid[state]:connect(function ()
- active = false
- end)
- end
- for _,state in pairs(onStates) do
- humanoid[state]:connect(function (speed)
- active = (speed>1)
- end)
- end
- local function glideTorwards(currentValue,targetValue,rate)
- if currentValue < targetValue then
- return math.min(targetValue,currentValue + rate)
- elseif currentValue > targetValue then
- return math.max(targetValue,currentValue - rate)
- else
- return targetValue
- end
- end
- local function getCamBobble()
- local goal = active and 0.5 or 0
- waveScale = glideTorwards(waveScale,goal,0.05)
- local t = math.cos(tick() * 7.85)
- return CFrame.new((t/3)*waveScale,math.abs(t/5)*waveScale,0)
- end
- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- -- Build Viewmodel
- local limbs = {}
- local vm = Instance.new("Model")
- vm.Name = "ViewModel"
- local h = Instance.new("Humanoid",vm)
- local function newLimb(name,size)
- local limb = Instance.new("Part",vm)
- limb.FormFactor = "Custom"
- limb.Name = name
- limb.Size = size
- limb.Anchored = true
- if size.magnitude < 0.4 then
- limb.Transparency = 1
- end
- table.insert(limbs,limb)
- return limb
- end
- local function newJoint(name,p0,p1)
- local j = Instance.new("Motor6D",p0)
- j.Name = name
- j.Part0 = p0
- j.Part1 = p1
- end
- local torso = newLimb("Torso",Vector3.new(2,2,1))
- local head = newLimb("Head",Vector3.new())
- local leftarm = newLimb("Left Arm",Vector3.new(1,2,1))
- local rightarm = newLimb("Right Arm",Vector3.new(1,2,1))
- vm.PrimaryPart = torso
- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- -- Break Humanoid Collisions using a nasty hack.
- spawn(function ()
- local cache = {}
- for _,limb in pairs(limbs) do
- cache[limb] = limb.Name
- limb.Name = "BREAK"
- end
- wait()
- for part,name in pairs(cache) do
- part.Name = name
- part.CanCollide = false
- end
- end)
- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- -- Character Object Tracking
- local toolEquipped = false
- local function trackTool(tool)
- -- This is a lot, but I need to make sure I carefully track tools
- -- as they can be unpredictable
- local cons = {}
- local parts = {}
- toolEquipped = true
- local function watchPart(handle)
- local repHandle = handle:clone()
- repHandle.Parent = vm
- repHandle.CanCollide = false
- repHandle.Anchored = true
- local function visualUpdate()
- local shouldHide = (c.Focus.p-c.CoordinateFrame.p).magnitude < 1
- handle.LocalTransparencyModifier = shouldHide and 1 or 0
- local relative = charTorso.CFrame:toObjectSpace(handle.CFrame)
- if repHandle then
- repHandle.CFrame = torso.CFrame * relative
- end
- end
- local con = rs.RenderStepped:connect(visualUpdate)
- table.insert(cons,rs.RenderStepped:connect(visualUpdate))
- table.insert(parts,repHandle)
- end
- local function initWatch(child)
- if child:IsA("BasePart") then
- watchPart(child)
- end
- end
- for _,child in pairs(tool:GetChildren()) do
- initWatch(child)
- end
- table.insert(cons,tool.ChildAdded:connect(initWatch))
- local function onUnequipped()
- toolEquipped = false
- for _,con in pairs(cons) do
- con:disconnect()
- end
- for _,part in pairs(parts) do
- pcall(function ()
- part:Destroy()
- end)
- end
- end
- table.insert(cons,tool.Unequipped:connect(onUnequipped))
- end
- local function pullObject(child)
- if child:IsA("CharacterAppearance") then
- child:clone().Parent = vm
- elseif child:IsA("Tool") then
- trackTool(child)
- end
- end
- for _,child in pairs(char:GetChildren()) do
- pullObject(child)
- end
- for _,part in pairs(vm:GetChildren()) do
- Spawn(function ()
- if part:IsA("BasePart") and part.Name ~= "Handle" then
- local actual = char:WaitForChild(part.Name)
- part.BrickColor = actual.BrickColor
- actual.Changed:connect(function ()
- actual.BrickColor = part.BrickColor
- end)
- end
- end)
- end
- char.ChildAdded:connect(pullObject)
- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- -- Camera Code
- if c:findFirstChild("ViewModel") then
- c.ViewModel:Destroy()
- end
- wait(1)
- local function renderUpdate()
- -- Figure out where the head is in the world relative to the HumanoidRootPart (and its base camera offset)
- local offset = CFrame.new()
- local bobble = getCamBobble()
- if (c.Focus.p-c.CoordinateFrame.p).magnitude <= 1 then -- If we are in first person...
- -- Sync the viewmodel joints with the character joints
- vm.Parent = c
- for _,part in pairs(limbs) do
- local actual = char:findFirstChild(part.Name)
- if actual then
- part.BrickColor = actual.BrickColor
- part.CFrame = torso.CFrame * charTorso.CFrame:toObjectSpace(actual.CFrame)
- end
- end
- -- Move our viewmodel relative to the camera
- vm:SetPrimaryPartCFrame(c.CoordinateFrame * CFrame.new(0,-1.5,-1) * bobble:inverse())
- -- Offset the camera based on where the head is in the world relative to the HumanoidRootPart
- local neckOffset = (charTorso.Position-charHead.Position).magnitude
- local expectedHeadPos = root.CFrame * CFrame.new(0,neckOffset,0)
- offset = expectedHeadPos:toObjectSpace(charHead.CFrame)
- else
- -- Hide it for now.
- vm.Parent = nil
- end
- humanoid.CameraOffset = (offset * bobble).p
- end
- local con = rs.RenderStepped:connect(renderUpdate)
- local function onDied()
- con:disconnect()
- vm:Destroy()
- end
- humanoid.Died:connect(onDied)
- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement