JIT
make foot targets visible for all players in roblox studio script
For this script for Roblox Studio, all I want now is for the leftfoot target and rightfoot target to be visible so each player sees each other's foot targets: -- Enhanced R6 IK with Wall Walking Physics local RunService = game:GetService("RunService") local UserInputService = game:GetService("UserInputService") local Players = game:GetService("Players") local Workspace = game:GetService("Workspace") -- Configuration local FOOT_HEIGHT_OFFSET = 0.3 local MAX_STEP_HEIGHT = 0.4 local STEP_SPEED = 11 local FOOT_DISTANCE = 1.5 local FOOT_WIDTH = 1.5 local ARM_SWING_AMOUNT = 10 local LEG_LERP_SPEED = 20.0 local ARM_LERP_SPEED = 15.0 local MOVE_SPEED = 18 local TURN_SPEED = 43 local GROUND_CHECK_DISTANCE = 0.5 local REQUIRED_GROUND_ANGLE = math.rad(45) local CLIMB_CHECK_DISTANCE = 3.0 local JUMP_POWER = 10 local JUMP_BOUNCE = 10 local ANCHOR_DELAY = 0 local ARM_ANCHOR_HEIGHT = 0.5 local CLIMB_GRAB_DISTANCE = 5 local CLIMB_PULL_FORCE = 5 local SPIDER_LEG_SPREAD = 5 -- Wall Walking Physics local WALL_WALK_GRAVITY = 1 local WALL_JUMP_FORCE = 10 local WALL_STICK_FORCE = 300 local CAMERA_LERP_SPEED = 0 local MAX_WALL_ANGLE = math.rad(45) local WALL_CHECK_DISTANCE = 5 -- Services local Players = game:GetService("Players") local Camera = workspace.CurrentCamera -- Create shared folders for all players to see local sharedIKFolder = Instance.new("Folder") sharedIKFolder.Name = "SharedIKTargets" sharedIKFolder.Parent = workspace -- Persistent arm storage local armTargetsFolder = Instance.new("Folder") armTargetsFolder.Name = "IKArmTargets" armTargetsFolder.Parent = workspace -- Get character local player = Players.LocalPlayer local character = player.Character or player.CharacterAdded:Wait() local humanoid = character:WaitForChild("Humanoid") local rootPart = character:WaitForChild("HumanoidRootPart") -- Wall Walking State local currentWallNormal = Vector3.new(0, 1, 0) local isWallWalking = false local lastWallNormal = Vector3.new(0, 1, 0) -- Function to create or get arm targets with collision local function ensureArmTargets() local leftArmTarget = armTargetsFolder:FindFirstChild("LeftArmIKTarget") local rightArmTarget = armTargetsFolder:FindFirstChild("RightArmIKTarget") if not leftArmTarget then leftArmTarget = Instance.new("Part") leftArmTarget.Name = "LeftArmIKTarget" leftArmTarget.Anchored = true leftArmTarget.CanCollide = false leftArmTarget.Transparency = 0.5 leftArmTarget.Color = Color3.fromRGB(255, 0, 0) leftArmTarget.Size = Vector3.new(1, 1, 1) leftArmTarget.Parent = armTargetsFolder local collision = Instance.new("BallSocketConstraint") collision.Parent = leftArmTarget end if not rightArmTarget then rightArmTarget = leftArmTarget:Clone() rightArmTarget.Name = "RightArmIKTarget" rightArmTarget.Color = Color3.fromRGB(0, 0, 255) rightArmTarget.Parent = armTargetsFolder end return leftArmTarget, rightArmTarget end -- Function to setup character parts with shared foot targets local function setupCharacterParts() local leftLeg = character:FindFirstChild("Left Leg") local rightLeg = character:FindFirstChild("Right Leg") local leftArm = character:FindFirstChild("Left Arm") local rightArm = character:FindFirstChild("Right Arm") -- Create foot targets in shared folder if they don't exist local playerFootFolder = sharedIKFolder:FindFirstChild(player.Name) if not playerFootFolder then playerFootFolder = Instance.new("Folder") playerFootFolder.Name = player.Name playerFootFolder.Parent = sharedIKFolder end if not playerFootFolder:FindFirstChild("LeftFootIKTarget") then local leftFootTarget = Instance.new("Part") leftFootTarget.Name = "LeftFootIKTarget" leftFootTarget.Anchored = true leftFootTarget.CanCollide = false leftFootTarget.Transparency = 0 leftFootTarget.Color = Color3.fromRGB(0, 255, 0) leftFootTarget.Size = Vector3.new(1, 1, 2.45) leftFootTarget.Parent = playerFootFolder end if not playerFootFolder:FindFirstChild("RightFootIKTarget") then local rightFootTarget = playerFootFolder.LeftFootIKTarget:Clone() rightFootTarget.Name = "RightFootIKTarget" rightFootTarget.Parent = playerFootFolder end return leftLeg, rightLeg, leftArm, rightArm, playerFootFolder end local leftLeg, rightLeg, leftArm, rightArm, playerFootFolder = setupCharacterParts() local leftArmTarget, rightArmTarget = ensureArmTargets() -- Movement state local moveDir = Vector3.new() local turnDir = 0 local isMoving = false local isJumping = false local isClimbing = false local lastMoveTime = 0 local lastGroundTime = 0 local anchorFeet = false local anchorArms = false -- Limb states local limbs = { leftFoot = { currentPos = Vector3.new(), targetPos = Vector3.new(), stepProgress = 0, moving = false }, rightFoot = { currentPos = Vector3.new(), targetPos = Vector3.new(), stepProgress = 0, moving = false }, leftArm = { swingPhase = 0, swingDir = 1, anchorProgress = 0, isGrabbing = false }, rightArm = { swingPhase = math.pi, swingDir = -1, anchorProgress = 0, isGrabbing = false } } -- Raycast setup local rayParams = RaycastParams.new() rayParams.FilterDescendantsInstances = {character} rayParams.FilterType = Enum.RaycastFilterType.Exclude -- Helper functions local function lerp(a, b, t) return a + (b - a) * math.clamp(t, 0, 1) end local function findGround(position) local origin = position + Vector3.new(0, 2, 0) local ray = workspace:Raycast(origin, Vector3.new(0, -GROUND_CHECK_DISTANCE, 0), rayParams) if ray and math.acos(ray.Normal:Dot(Vector3.new(0, 1, 0))) < REQUIRED_GROUND_ANGLE then lastGroundTime = os.clock() return ray.Position + Vector3.new(0, FOOT_HEIGHT_OFFSET, 0), ray.Normal end return position - Vector3.new(0, GROUND_CHECK_DISTANCE - FOOT_HEIGHT_OFFSET, 0), Vector3.new(0, 1, 0) end -- Wall detection similar to referenced asset local function checkForWalls() local origin = rootPart.Position local params = RaycastParams.new() params.FilterDescendantsInstances = {character} params.FilterType = Enum.RaycastFilterType.Exclude -- Check in multiple directions for walls local directions = { rootPart.CFrame.LookVector, -rootPart.CFrame.LookVector, rootPart.CFrame.RightVector, -rootPart.CFrame.RightVector } for _, dir in ipairs(directions) do local ray = workspace:Raycast(origin, dir * WALL_CHECK_DISTANCE, params) if ray and ray.Instance.CanCollide then local angle = math.acos(ray.Normal:Dot(Vector3.new(0, 1, 0))) if angle > MAX_WALL_ANGLE then return ray.Position, ray.Normal end end end return nil end -- Enhanced spider-like climbing detection local function findClimbSurface(armPosition, direction) local origin = armPosition local ray = workspace:Raycast(origin, direction.Unit * CLIMB_GRAB_DISTANCE, rayParams) if ray and ray.Instance.CanCollide then local angle = math.acos(ray.Normal:Dot(Vector3.new(0, 1, 0))) if angle > math.rad(20) and angle < math.rad(160) then return ray.Position, ray.Normal end end return nil end -- Foot movement local function updateFoot(dt, state, otherState, targetPart, offset) local rootPos = rootPart.Position local rootCF = rootPart.CFrame local desiredPos = rootPos + rootCF:VectorToWorldSpace(offset) state.targetPos = findGround(desiredPos) local dist = (state.targetPos - state.currentPos).Magnitude if dist > 0.5 and not state.moving and not otherState.moving and not anchorFeet then state.moving = true state.stepProgress = 0 end if state.moving then state.stepProgress = state.stepProgress + dt * STEP_SPEED if state.stepProgress >= 1 then state.currentPos = state.targetPos state.moving = false else local t = state.stepProgress local height = math.sin(t * math.pi) * MAX_STEP_HEIGHT local mid = (state.currentPos + state.targetPos) * 0.5 + Vector3.new(0, height, 0) state.currentPos = lerp(lerp(state.currentPos, mid, t), lerp(mid, state.targetPos, t), t) end end targetPart.CFrame = CFrame.new(state.currentPos) * CFrame.Angles(math.rad(-90), 0, 0) end -- Enhanced spider-like arm movement with climbing and camera adjustment local function updateArm(dt, state, side, targetPart, arm) local rootPos = rootPart.Position local rootCF = rootPart.CFrame -- Check for climbable surfaces if isMoving and not isJumping then local armOffset = Vector3.new(side * SPIDER_LEG_SPREAD, 0, 0) local armWorldPos = rootPos + rootCF:VectorToWorldSpace(armOffset) local lookDir = rootCF.LookVector local climbPos, climbNormal = findClimbSurface(armWorldPos, lookDir) if climbPos then state.isGrabbing = true state.climbPos = climbPos state.climbNormal = climbNormal isClimbing = true else state.isGrabbing = false isClimbing = limbs.leftArm.isGrabbing or limbs.rightArm.isGrabbing end else state.isGrabbing = false isClimbing = false end if state.isGrabbing then -- Spider climbing behavior local grabPos = state.climbPos + (state.climbNormal * 0.3) local armRot = CFrame.lookAt(grabPos, grabPos + state.climbNormal) targetPart.CFrame = armRot * CFrame.Angles(math.rad(90), 0, 0) -- Apply climbing pull force if isMoving then local alongWall = rootCF.RightVector:Dot(state.climbNormal) * state.climbNormal local moveDirection = (rootCF.LookVector - alongWall).Unit rootPart.Velocity = moveDirection * MOVE_SPEED + (state.climbNormal * CLIMB_PULL_FORCE) end else -- Normal arm movement if not isMoving and not isJumping then state.anchorProgress = math.min(state.anchorProgress + dt * 2, 1) else state.anchorProgress = math.max(state.anchorProgress - dt * 3, 0) end if state.anchorProgress > 0 then -- Anchored arm position local anchorOffset = Vector3.new(side * 1.5, -ARM_ANCHOR_HEIGHT * state.anchorProgress, 0) local armPos = rootPos + rootCF:VectorToWorldSpace(anchorOffset) local armRot = CFrame.Angles(math.rad(-20), 0, math.rad(side * -10)) targetPart.CFrame = CFrame.new(armPos) * armRot else -- Normal swinging behavior if isMoving then state.swingPhase = state.swingPhase + dt * 5 * state.swingDir else state.swingPhase = lerp(state.swingPhase, side == 1 and math.pi or 0, dt * 2) end local armOffset = Vector3.new(side * 1.5, 0.5, 0) local swingOffset = Vector3.new(0, 0, math.sin(state.swingPhase) * ARM_SWING_AMOUNT) local armPos = rootPos + rootCF:VectorToWorldSpace(armOffset + swingOffset) local armRot = CFrame.Angles(math.rad(-20), 0, math.rad(side * -10)) targetPart.CFrame = CFrame.new(armPos) * armRot end end -- Apply to actual arm with collision if arm then arm.CFrame = arm.CFrame:Lerp(targetPart.CFrame, dt * ARM_LERP_SPEED) arm.CanCollide = state.isGrabbing end end -- Wall walking physics update local function updateWallWalking(dt) local wallPos, wallNormal = checkForWalls() if wallNormal then -- Calculate new up vector based on wall normal local newUp = -wallNormal local newRight = rootPart.CFrame.RightVector - (rootPart.CFrame.RightVector:Dot(newUp)) * newUp local newLook = newUp:Cross(newRight).Unit -- Smoothly transition to wall orientation currentWallNormal = lerp(currentWallNormal, newUp, dt * 5) -- Apply wall stick force rootPart.Velocity = rootPart.Velocity + (currentWallNormal * WALL_STICK_FORCE * dt) -- Adjust gravity Workspace.Gravity = WALL_WALK_GRAVITY -- Rotate character to match wall rootPart.CFrame = CFrame.new(rootPart.Position, rootPart.Position + newLook) * CFrame.fromMatrix(Vector3.new(), newRight, newUp, newLook) -- Adjust camera local camCF = Camera.CFrame local newCamLook = camCF.LookVector - (camCF.LookVector:Dot(currentWallNormal)) * currentWallNormal Camera.CFrame = CFrame.new(camCF.Position, camCF.Position + newCamLook) isWallWalking = true lastWallNormal = wallNormal else -- Return to normal gravity Workspace.Gravity = 196.2 isWallWalking = false end end -- Movement handling local function updateMovement(dt) local now = os.clock() local wasMoving = isMoving isMoving = moveDir.Magnitude > 0 if isMoving then lastMoveTime = now anchorFeet = false if turnDir ~= 0 and moveDir.Z == 0 then humanoid.AutoRotate = false rootPart.CFrame = rootPart.CFrame * CFrame.Angles(0, turnDir * TURN_SPEED * dt, 0) else humanoid.AutoRotate = true end local moveVector = rootPart.CFrame:VectorToWorldSpace(moveDir) * MOVE_SPEED if not isClimbing and not isWallWalking then rootPart.Velocity = Vector3.new(moveVector.X, rootPart.Velocity.Y, moveVector.Z) end else humanoid.AutoRotate = true if wasMoving and now - lastMoveTime > ANCHOR_DELAY then anchorFeet = true end if not isJumping and rootPart.Velocity.Y > -5 then rootPart.Velocity = Vector3.new(0, rootPart.Velocity.Y, 0) end end end -- Enhanced jump with wall jump local function handleJump() if isJumping then return end if isWallWalking then -- Wall jump isJumping = true local jumpDir = (rootPart.CFrame.LookVector + lastWallNormal).Unit rootPart.Velocity = jumpDir * WALL_JUMP_FORCE isWallWalking = false delay(0.5, function() isJumping = false end) else -- Normal jump local groundPos = findGround(rootPart.Position) if (os.clock() - lastGroundTime) < 0.1 then isJumping = true rootPart.Velocity = Vector3.new(rootPart.Velocity.X, JUMP_POWER, rootPart.Velocity.Z) leftLeg.CFrame = leftLeg.CFrame * CFrame.new(0, -JUMP_BOUNCE, 0) rightLeg.CFrame = rightLeg.CFrame * CFrame.new(0, -JUMP_BOUNCE, 0) delay(0.5, function() isJumping = false end) end end end -- Main update local function update(dt) if not rootPart or not rootPart.Parent then return end updateMovement(dt) updateWallWalking(dt) local moveOffset = Vector3.new(moveDir.X * FOOT_DISTANCE, 0, moveDir.Z * FOOT_DISTANCE) if not isJumping then updateFoot(dt, limbs.leftFoot, limbs.rightFoot, playerFootFolder.LeftFootIKTarget, Vector3.new(-FOOT_WIDTH, 0, -FOOT_DISTANCE/2) + moveOffset) updateFoot(dt, limbs.rightFoot, limbs.leftFoot, playerFootFolder.RightFootIKTarget, Vector3.new(FOOT_WIDTH, 0, -FOOT_DISTANCE/2) + moveOffset) end updateArm(dt, limbs.leftArm, -1, leftArmTarget, leftArm) updateArm(dt, limbs.rightArm, 1, rightArmTarget, rightArm) if not isJumping then leftLeg.CFrame = leftLeg.CFrame:Lerp(CFrame.new(limbs.leftFoot.currentPos), dt * LEG_LERP_SPEED) rightLeg.CFrame = rightLeg.CFrame:Lerp(CFrame.new(limbs.rightFoot.currentPos), dt * LEG_LERP_SPEED) end end -- Input handling UserInputService.InputBegan:Connect(function(input) if input.KeyCode == Enum.KeyCode.W then moveDir = Vector3.new(0, 0, -1) elseif input.KeyCode == Enum.KeyCode.S then moveDir = Vector3.new(0, 0, 1) elseif input.KeyCode == Enum.KeyCode.A then if UserInputService:IsKeyDown(Enum.KeyCode.LeftShift) then turnDir = -1 else moveDir = Vector3.new(-1, 0, 0) end elseif input.KeyCode == Enum.KeyCode.D then if UserInputService:IsKeyDown(Enum.KeyCode.LeftShift) then turnDir = 1 else moveDir = Vector3.new(1, 0, 0) end elseif input.KeyCode == Enum.KeyCode.Space then handleJump() end end) UserInputService.InputEnded:Connect(function(input) if input.KeyCode == Enum.KeyCode.W or input.KeyCode == Enum.KeyCode.S then if moveDir.Z ~= 0 then moveDir = Vector3.new(moveDir.X, 0, 0) end elseif input.KeyCode == Enum.KeyCode.A or input.KeyCode == Enum.KeyCode.D then if moveDir.X ~= 0 then moveDir = Vector3.new(0, 0, moveDir.Z) end turnDir = 0 end end) -- Initialize local function init() -- Re-get character parts in case of reset leftLeg, rightLeg, leftArm, rightArm, playerFootFolder = setupCharacterParts() local rootPos = rootPart.Position local rootCF = rootPart.CFrame limbs.leftFoot.currentPos = findGround(rootPos + rootCF:VectorToWorldSpace(Vector3.new(-FOOT_WIDTH, 0, 0))) limbs.rightFoot.currentPos = findGround(rootPos + rootCF:VectorToWorldSpace(Vector3.new(FOOT_WIDTH, 0, 0))) playerFootFolder.LeftFootIKTarget.CFrame = CFrame.new(limbs.leftFoot.currentPos) * CFrame.Angles(math.rad(-90), 0, 0) playerFootFolder.RightFootIKTarget.CFrame = CFrame.new(limbs.rightFoot.currentPos) * CFrame.Angles(math.rad(-90), 0, 0) if leftArm and rightArm then leftArmTarget.CFrame = CFrame.new(rootPos + rootCF:VectorToWorldSpace(Vector3.new(-1.5, 0.5, 0))) * CFrame.Angles(math.rad(-20), 0, math.rad(10)) rightArmTarget.CFrame = CFrame.new(rootPos + rootCF:VectorToWorldSpace(Vector3.new(1.5, 0.5, 0))) * CFrame.Angles(math.rad(-20), 0, math.rad(-10)) end end -- Handle character reset player.CharacterAdded:Connect(function(newCharacter) character = newCharacter humanoid = character:WaitForChild("Humanoid") rootPart = character:WaitForChild("HumanoidRootPart") leftLeg, rightLeg, leftArm, rightArm, playerFootFolder = setupCharacterParts() -- Reinitialize with existing arm targets init() end) init() RunService.Heartbeat:Connect(update) print("Enhanced R6 IK with Wall Walking Physics Active")
Updated files
v1