I’m trying to create a ledge climbing system similar to the one in rogue lineage
Currently it can deal with parts rotated like this https://gyazo.com/f10aae7adbe54a1157b2f86c4375ed81
but it can’t deal with parts like these https://gyazo.com/65f6f0c93b7abfa81c5df8cc5f0fe595
I’m not sure how i would fix this since im pretty new to CFrame manipulation
Script location
https://gyazo.com/fe6afd666266ffdf609c5802eafe4642
Client side code
local UIS = game:GetService("UserInputService")
UIS.InputBegan:Connect(function(key, processed)
if key.KeyCode == Enum.KeyCode.Space then
script.grab:FireServer()
end
end)
Server side code
local char = script.Parent
local humanoid = char:WaitForChild("Humanoid")
local uisHandler = script.Parent.UISHandler
local debrisService = game:GetService("Debris")
local animator = Instance.new("Animator", humanoid)
local inuse = false
local debounce = true
local ledgeHoldAnim = animator:LoadAnimation(script.ledgeHold)
function getSurface(position, object)
local surfaces = {
back = object.CFrame * CFrame.new(0, 0, object.Size.Z);
front = object.CFrame * CFrame.new(0, 0, -object.Size.Z);
top = object.CFrame * CFrame.new(0, object.Size.Y, 0);
bottom = object.CFrame * CFrame.new(0, -object.Size.Y, 0);
right = object.CFrame * CFrame.new(object.Size.X, 0, 0);
left = object.CFrame * CFrame.new(-object.Size.X, 0, 0);
}
local surface = "back"
for side, cframe in pairs (surfaces) do
surface = ((position - cframe.p).magnitude > (position - surfaces[surface].p).magnitude and surface or side)
end
return surface, CFrame.new(surfaces[surface].p, object.Position)
end
local grabEvent = uisHandler.grab.OnServerEvent:Connect(function()
local state = humanoid:GetState()
local head = char.Head
local root = char.HumanoidRootPart
if humanoid.Health > 0 and not inuse then
local r = Ray.new(root.CFrame.p, root.CFrame.LookVector * 5)
local part, position = workspace:FindPartOnRay(r, char)
if part ~= nil then
if part.Velocity == Vector3.new(0, 0, 0) and debounce and part.CanCollide == true then
debounce = false
local face, faceCFrame = getSurface(position, part)
local newFaceCFramePos = Vector3.new(position.X, part.Position.Y + part.Size.Y / 2, position.Z)
local newFaceCFrameRot = newFaceCFramePos
local faceCFrameAngle = faceCFrame - faceCFrame.Position
ledge = (faceCFrameAngle + newFaceCFramePos) * CFrame.new(Vector3.new(0, -1, 1))
local distance = (root.Position - ledge.Position).magnitude
if distance <= 5 and face ~= "top" and face ~= "bottom" then
inuse = true
ledgeHoldAnim:Play()
humanoid.AutoRotate = false
root.Anchored = true
root.CFrame = ledge
end
debounce = true
end
end
elseif humanoid.Health > 0 and inuse and debounce then
debounce = false
humanoid.AutoRotate = true
root.Anchored = false
ledge = ledge * CFrame.new(Vector3.new(0, 4, -2))
local bp = Instance.new("BodyPosition")
local bg = Instance.new("BodyGyro")
bp.Parent = root
bg.Parent = root
bp.MaxForce = Vector3.new(math.huge, math.huge, math.huge)
bp.D = 800
bp.Position = ledge.Position
bg.MaxTorque = Vector3.new(math.huge, math.huge, math.huge)
bg.D = 800
bg.CFrame = ledge
ledgeHoldAnim:Stop()
debrisService:AddItem(bp, 0.5)
debrisService:AddItem(bg, 0.5)
inuse = false
wait(.5)
debounce = true
end
end)