--[[ TELEKINESIS V3 COMPLETO MEJORADO Versión móvil mejorada + Todas las características de PC Los dedos se ignoran en móvil, solo botones y puntero azul Botón de anclar debajo del de lanzar Fecha: 2026-04-01 ]] -- [[ SERVICIOS ]] local player = game.Players.LocalPlayer local mouse = player:GetMouse() local camera = workspace.CurrentCamera local humanoidRootPart = player.Character and player.Character:FindFirstChild("HumanoidRootPart") local run, UIS = game:GetService("RunService"), game:GetService("UserInputService") local isMobile = UIS.TouchEnabled -- [[ VARIABLES DE ESTADO ]] local holding, target, holdDistance, anchoredWhileHolding = false, nil, 10, false local scriptActive = true local fuerzaLanzamiento = 1000 local fuerzaLanzamientoMin, fuerzaLanzamientoMax = 100, 4000 -- Variables para movimiento constante y arrastre local holdFar, holdClose = false, false local draggingPointer = false -- [[ FÍSICAS ]] local vel = Instance.new("BodyVelocity") vel.MaxForce = Vector3.new(1, 1, 1) * 1e5 vel.P = 12500 local gyro = Instance.new("BodyGyro") gyro.MaxTorque = Vector3.new(1, 1, 1) * 1e6 gyro.P = 3000 local originalRotation = nil local originalPhysicalProperties = {} -- Sistema de Rotación local rotationMode = false local lastMouseX = 0 local lastMouseY = 0 local rotationSensitivity = 0.8 local fixedCameraPosition = nil local fixedCameraRotation = nil local fixedObjectPosition = nil local positionLock = Instance.new("BodyVelocity") positionLock.MaxForce = Vector3.new(1, 1, 1) * 1e5 positionLock.P = 12500 positionLock.Velocity = Vector3.new(0, 0, 0) local originalCharacterVisibility = {} local characterHidden = false -- [[ HIGHLIGHTS ]] local highlightHolding = Instance.new("Highlight") highlightHolding.OutlineColor = Color3.fromRGB(0, 255, 0) highlightHolding.FillColor = Color3.fromRGB(0, 255, 0) highlightHolding.FillTransparency = 0.5 highlightHolding.OutlineTransparency = 0 highlightHolding.DepthMode = Enum.HighlightDepthMode.Occluded highlightHolding.Parent = game:GetService("CoreGui") local highlightLooking = Instance.new("Highlight") highlightLooking.OutlineColor = Color3.fromRGB(0, 170, 255) highlightLooking.FillColor = Color3.fromRGB(0, 170, 255) highlightLooking.FillTransparency = 0.6 highlightLooking.OutlineTransparency = 0 highlightLooking.DepthMode = Enum.HighlightDepthMode.Occluded highlightLooking.Parent = game:GetService("CoreGui") -- [[ IMÁN ]] local imanActivo, radioIman, fuerzaIman = false, 30, 200 local objetosIman, gravityBackup = {}, {} local fuerzaImanMin, fuerzaImanMax = 50, 2000 -- Círculo visual avanzado local usingDrawing = Drawing and Drawing.new and typeof(Drawing.new)=="function" local imancircle, circleGui, circleImg local circleColor = Color3.fromRGB(0,170,255) local surfacePos, surfaceNormal = Vector3.zero, Vector3.new(0,1,0) local actualRadio = radioIman if usingDrawing then imancircle = Drawing.new("Circle") imancircle.Visible, imancircle.Transparency, imancircle.Color, imancircle.Thickness, imancircle.Filled = false, 1, circleColor, 2, false else circleGui = Instance.new("BillboardGui") circleGui.Name, circleGui.Size, circleGui.SizeOffset, circleGui.AlwaysOnTop = "ImanCircleGui", UDim2.new(2,0,2,0), Vector2.new(0,0), true circleGui.Parent = workspace circleImg = Instance.new("ImageLabel") circleImg.BackgroundTransparency, circleImg.Image, circleImg.ImageColor3 = 1, "rbxassetid://13523341990", circleColor circleImg.AnchorPoint, circleImg.Position, circleImg.Size = Vector2.new(0.5,0.5), UDim2.fromScale(0.5,0.5), UDim2.fromScale(1,1) circleImg.Parent, circleGui.Enabled = circleGui, false end -- [[ GUI PC - SOLO PARA COMPUTADORA ]] local fuerzaGui = Instance.new("ScreenGui") fuerzaGui.Name = "FuerzaImanGui" fuerzaGui.Parent = game:GetService("CoreGui") fuerzaGui.Enabled = not isMobile local fuerzaLabel = Instance.new("TextLabel") fuerzaLabel.Name = "FuerzaImanLabel" fuerzaLabel.BackgroundTransparency = 0.3 fuerzaLabel.BackgroundColor3 = Color3.fromRGB(30, 30, 30) fuerzaLabel.Size = UDim2.new(0, 220, 0, 60) fuerzaLabel.Position = UDim2.new(1, -230, 1, -70) fuerzaLabel.TextScaled = true fuerzaLabel.Font = Enum.Font.GothamBold fuerzaLabel.TextColor3 = Color3.new(1,1,1) fuerzaLabel.TextStrokeTransparency = 0.5 fuerzaLabel.Visible = true local corner = Instance.new("UICorner") corner.CornerRadius = UDim.new(0, 12) corner.Parent = fuerzaLabel fuerzaLabel.Parent = fuerzaGui -- GUI para modo rotación (solo PC) local rotationGui = Instance.new("ScreenGui") rotationGui.Name = "RotationModeGui" rotationGui.Parent = game:GetService("CoreGui") rotationGui.Enabled = not isMobile local rotationLabel = Instance.new("TextLabel") rotationLabel.Name = "RotationLabel" rotationLabel.BackgroundTransparency = 0.3 rotationLabel.BackgroundColor3 = Color3.fromRGB(30, 30, 30) rotationLabel.Size = UDim2.new(0, 220, 0, 60) rotationLabel.Position = UDim2.new(1, -230, 1, -70) rotationLabel.TextScaled = true rotationLabel.Font = Enum.Font.GothamBold rotationLabel.TextColor3 = Color3.new(1,1,1) rotationLabel.TextStrokeTransparency = 0.5 rotationLabel.Visible = false rotationLabel.Text = "🔄 ROTACIÓN\n▲▼◄►" local rotationCorner = Instance.new("UICorner") rotationCorner.CornerRadius = UDim.new(0, 12) rotationCorner.Parent = rotationLabel rotationLabel.Parent = rotationGui -- [[ GUI MÓVIL - MEJORADA ]] local mobileGui = Instance.new("ScreenGui") mobileGui.Name = "TelekinesisV3" mobileGui.Parent = game:GetService("CoreGui") mobileGui.Enabled = isMobile mobileGui.ResetOnSpawn = false local buttonContainer = Instance.new("Frame") buttonContainer.Size = UDim2.new(1, 0, 1, 0) buttonContainer.BackgroundTransparency = 1 buttonContainer.Parent = mobileGui -- PUNTERO AZUL ARRASTRABLE - SOLO PARA INTERFACE local fakePointer = Instance.new("Frame") fakePointer.Size = UDim2.new(0, 35, 0, 35) fakePointer.Position = UDim2.new(0.5, 0, 0.4, 0) fakePointer.AnchorPoint = Vector2.new(0.5, 0.5) fakePointer.BackgroundColor3 = Color3.fromRGB(0, 170, 255) fakePointer.BackgroundTransparency = 0.4 fakePointer.Active = true fakePointer.Parent = mobileGui fakePointer.ZIndex = 100 Instance.new("UICorner", fakePointer).CornerRadius = UDim.new(1, 0) local pointerStroke = Instance.new("UIStroke", fakePointer) pointerStroke.Color = Color3.new(1,1,1) pointerStroke.Thickness = 2 -- Lógica para mover el puntero con el dedo - SOLO RESPONDE AL PUNTERO fakePointer.InputBegan:Connect(function(input) if input.UserInputType == Enum.UserInputType.Touch or input.UserInputType == Enum.UserInputType.MouseButton1 then draggingPointer = true end end) UIS.InputChanged:Connect(function(input) if draggingPointer and (input.UserInputType == Enum.UserInputType.Touch or input.UserInputType == Enum.UserInputType.MouseMovement) then fakePointer.Position = UDim2.new(0, input.Position.X - 17.5, 0, input.Position.Y - 17.5) end end) UIS.InputEnded:Connect(function(input) if input.UserInputType == Enum.UserInputType.Touch or input.UserInputType == Enum.UserInputType.MouseButton1 then draggingPointer = false end end) -- Función para crear botón local function crearBoton(name, pos, text, color, size) local btn = Instance.new("TextButton") btn.Name = name btn.Size = size or UDim2.new(0, 75, 0, 65) btn.Position = pos btn.BackgroundColor3 = color btn.Text = text btn.TextScaled = true btn.Font = Enum.Font.GothamBold btn.TextColor3 = Color3.new(1,1,1) btn.ZIndex = 100 local corner = Instance.new("UICorner") corner.CornerRadius = UDim.new(0, 12) corner.Parent = btn btn.Parent = buttonContainer return btn end -- BOTONES DE CONTROL (POSICIONES OPTIMIZADAS) local btnFDown = crearBoton("FDown", UDim2.new(0, 10, 0, 10), "⬇️\n-Fuerza", Color3.fromRGB(255, 100, 100)) local btnFUp = crearBoton("FUp", UDim2.new(0, 95, 0, 10), "⬆️\n+Fuerza", Color3.fromRGB(100, 255, 100)) -- Botones de Distancia (VELOCIDAD SUAVE 0.8) local btnClose = crearBoton("Close", UDim2.new(0, 10, 0, 85), "📏\n➖", Color3.fromRGB(100, 200, 255)) local btnFar = crearBoton("Far", UDim2.new(0, 95, 0, 85), "📏\n➕", Color3.fromRGB(100, 200, 255)) -- Botones de Acción local btnThrow = crearBoton("Throw", UDim2.new(1, -90, 0, 85), "🔥\nLanzar", Color3.fromRGB(255, 100, 100), UDim2.new(0, 80, 0, 65)) local btnAnchor = crearBoton("Anchor", UDim2.new(1, -90, 0, 160), "📌\nAnclar", Color3.fromRGB(255, 200, 0), UDim2.new(0, 80, 0, 65)) local btnHide = crearBoton("Hide", UDim2.new(1, -90, 0, 10), "👁️", Color3.fromRGB(150, 150, 150), UDim2.new(0, 80, 0, 65)) local btnGrab = crearBoton("Grab", UDim2.new(0.35, 0, 1, -110), "✋ Agarrar", Color3.fromRGB(0, 200, 0), UDim2.new(0.3, 0, 0, 80)) -- [[ VARIABLES DE CONTROL ]] local guiVisible = true local lastNotificationTime = 0 local notificationCooldown = 0.3 local holdQ, holdE = false, false -- [[ BLOQUEAR INTERACCIÓN TÁCTIL EN OBJETOS ]] -- Los dedos NO podrán agarrar objetos directamente, solo los botones funcionan local originalMouseButton1Down = mouse.Button1Down mouse.Button1Down:Connect(function() if not isMobile then agarrarOSoltar() end -- En móvil se ignora completamente end) -- [[ FUNCIONES AUXILIARES ]] local function notify(title, text, duration) if not scriptActive then return end local currentTime = tick() if currentTime - lastNotificationTime >= notificationCooldown then pcall(function() game:GetService("StarterGui"):SetCore("SendNotification", { Title = title, Text = text, Duration = duration or 1.2 }) end) lastNotificationTime = currentTime end end local function esParteDePersonaje(obj) for _, plr in ipairs(game.Players:GetPlayers()) do if plr.Character and obj:IsDescendantOf(plr.Character) then return true end end return false end local function tieneSoldaduraNoAnclada(obj) for _, c in ipairs(obj:GetConnectedParts()) do if c ~= obj and not c.Anchored then return true end end return false end local function restaurarGravedad() for obj, oldGravity in pairs(gravityBackup) do if obj and obj:IsDescendantOf(workspace) then obj.CustomPhysicalProperties = oldGravity gravityBackup[obj] = nil end end gravityBackup = {} end local function restaurarPropiedadesOriginales() for obj, props in pairs(originalPhysicalProperties) do if obj and obj:IsDescendantOf(workspace) then obj.CustomPhysicalProperties = props end end originalPhysicalProperties = {} end local function lerpVec3(a, b, t) return a + (b - a) * t end local function ocultarPersonaje() if not player.Character then return end characterHidden = true for _, part in ipairs(player.Character:GetDescendants()) do if part:IsA("BasePart") then originalCharacterVisibility[part] = part.Transparency part.Transparency = 1 end end local humanoid = player.Character:FindFirstChild("Humanoid") if humanoid then for _, accessory in ipairs(humanoid:GetChildren()) do if accessory:IsA("Accessory") then local handle = accessory:FindFirstChild("Handle") if handle then originalCharacterVisibility[handle] = handle.Transparency handle.Transparency = 1 end end end end end local function mostrarPersonaje() if not characterHidden then return end characterHidden = false for part, transparency in pairs(originalCharacterVisibility) do if part and part:IsDescendantOf(workspace) then part.Transparency = transparency end end originalCharacterVisibility = {} end local function bloquearMovimientoPersonaje() if humanoidRootPart then humanoidRootPart.Velocity = Vector3.new(0, 0, 0) end end -- Función para obtener información del rayo desde el puntero azul local function getPointInfo() if isMobile then local px = fakePointer.AbsolutePosition.X + (fakePointer.AbsoluteSize.X/2) local py = fakePointer.AbsolutePosition.Y + (fakePointer.AbsoluteSize.Y/2) local ray = camera:ScreenPointToRay(px, py) return Ray.new(ray.Origin, ray.Direction * 1000) else local ray = camera:ScreenPointToRay(mouse.X, mouse.Y) return Ray.new(ray.Origin, ray.Direction * 1000) end end local function alternarModoRotacion() if not holding or not target then notify("❌ No disponible", "Debes agarrar un objeto primero", 2) return end rotationMode = not rotationMode if rotationMode then fixedCameraPosition = camera.CFrame.Position fixedCameraRotation = camera.CFrame - camera.CFrame.Position fixedObjectPosition = target.Position vel.Parent = nil positionLock.Velocity = Vector3.new(0, 0, 0) positionLock.Parent = target lastMouseX = mouse.X lastMouseY = mouse.Y ocultarPersonaje() rotationLabel.Visible = true if not isMobile then fuerzaLabel.Visible = false end notify("🔄 MODO ROTACIÓN ACTIVADO", "Mueve el ratón para rotar | Presiona C para salir", 2) else fixedCameraPosition = nil fixedCameraRotation = nil fixedObjectPosition = nil rotationLabel.Visible = false positionLock.Parent = nil vel.Parent = target mostrarPersonaje() if guiVisible and scriptActive and not isMobile then if imanActivo then fuerzaLabel.Text = "🧲 Fuerza: "..math.floor(fuerzaIman).."\n📏 Radio: "..math.floor(radioIman) else fuerzaLabel.Text = "🎯 Lanzamiento: "..math.floor(fuerzaLanzamiento) end fuerzaLabel.Visible = true end notify("🔄 MODO ROTACIÓN DESACTIVADO", "Cámara y movimiento restaurados", 2) end end local function desactivarScript() scriptActive = false guiVisible = false rotationMode = false holdQ = false holdE = false if holding and target then vel.Parent = nil gyro.Parent = nil holding = false target = nil end if imanActivo then for obj in pairs(objetosIman) do if obj and obj:FindFirstChild("ImanBV") then obj.ImanBV:Destroy() end end objetosIman = {} restaurarPropiedadesOriginales() gravityBackup = {} imanActivo = false end highlightHolding.Adornee = nil highlightLooking.Adornee = nil if not isMobile then fuerzaGui.Enabled = false rotationGui.Enabled = false end if usingDrawing and imancircle then imancircle.Visible = false elseif circleGui then circleGui.Enabled = false end notify("🙈 Script Desactivado", "", 1) end local function activarScript() scriptActive = true guiVisible = true lastNotificationTime = 0 if not isMobile then fuerzaGui.Enabled = true rotationGui.Enabled = true end notify("👁️ Script Activado", "", 1) end -- [[ FUNCIONES DE ACCIÓN ]] function agarrarOSoltar() if not scriptActive then return end if imanActivo then return end if rotationMode then return end if holding then originalRotation = nil vel.Parent, gyro.Parent, anchoredWhileHolding, target, holding = nil, nil, false, nil, false if rotationMode then rotationMode = false fixedCameraPosition = nil fixedCameraRotation = nil fixedObjectPosition = nil rotationLabel.Visible = false positionLock.Parent = nil mostrarPersonaje() end if target and originalPhysicalProperties[target] then target.CustomPhysicalProperties = originalPhysicalProperties[target] originalPhysicalProperties[target] = nil end if isMobile then btnGrab.Text = "✋ Agarrar" btnGrab.BackgroundColor3 = Color3.fromRGB(0, 200, 0) end else local hit = workspace:FindPartOnRayWithIgnoreList(getPointInfo(), {player.Character}) if hit and hit:IsA("BasePart") and not esParteDePersonaje(hit) then if hit.Anchored then if not hit:GetAttribute("TelekinesisAnchored") then return end hit.Anchored = false hit:SetAttribute("TelekinesisAnchored", nil) end target, anchoredWhileHolding = hit, false originalRotation = hit.CFrame - hit.Position gyro.CFrame = originalRotation + hit.Position gyro.Parent = hit vel.Velocity, vel.Parent = Vector3.zero, hit local rayInfo = getPointInfo() local _, pos = workspace:FindPartOnRayWithIgnoreList(rayInfo, {player.Character}) holdDistance = pos and (camera.CFrame.Position - pos).Magnitude or (camera.CFrame.Position - hit.Position).Magnitude holding = true if isMobile then btnGrab.Text = "❌ Soltar" btnGrab.BackgroundColor3 = Color3.fromRGB(200, 0, 0) end notify("✋ Agarrado", "", 0.5) end end end function lanzar() if not scriptActive then return end if imanActivo then return end if rotationMode then return end if holding and target then if anchoredWhileHolding then target.Anchored, anchoredWhileHolding = false, false end vel.Parent, gyro.Parent, holding = nil, nil, false originalRotation = nil if originalPhysicalProperties[target] then target.CustomPhysicalProperties = originalPhysicalProperties[target] originalPhysicalProperties[target] = nil end local rayInfo = getPointInfo() local launchDirection = rayInfo.Direction.Unit local impulse = Instance.new("BodyVelocity") impulse.Velocity = launchDirection * fuerzaLanzamiento impulse.MaxForce, impulse.P, impulse.Parent = Vector3.new(1,1,1)*1e6, 12500, target game:GetService("Debris"):AddItem(impulse, 0.5) target = nil if isMobile then btnGrab.Text = "✋ Agarrar" btnGrab.BackgroundColor3 = Color3.fromRGB(0, 200, 0) end notify("🔥 Lanzado", "", 0.5) end end function alternarAnclado() if not scriptActive then return end if imanActivo then return end if rotationMode then return end if holding and target then anchoredWhileHolding = not anchoredWhileHolding target.Anchored = anchoredWhileHolding if anchoredWhileHolding then target:SetAttribute("TelekinesisAnchored", true) vel.Parent = nil gyro.Parent = nil target.AssemblyLinearVelocity = Vector3.zero target.AssemblyAngularVelocity = Vector3.zero local humanoidRoot = player.Character and player.Character:FindFirstChild("HumanoidRootPart") if humanoidRoot and (humanoidRoot.Position - target.Position).Magnitude < 5 then humanoidRoot.Velocity = Vector3.zero humanoidRoot.AssemblyLinearVelocity = Vector3.zero humanoidRoot.CFrame = humanoidRoot.CFrame + Vector3.new(0, 3, 0) end else target:SetAttribute("TelekinesisAnchored", nil) vel.Parent = target gyro.Parent = target end notify(anchoredWhileHolding and "📌 Anclado" or "📎 Desanclado", "", 0.5) end end function anclarMasivoIman() if not scriptActive then return end if not imanActivo then return end if holding then notify("❌ No disponible", "Suelta el objeto para usar anclaje masivo", 2) return end local count = 0 for obj in pairs(objetosIman) do if obj and obj:IsDescendantOf(workspace) then obj.Anchored = true obj:SetAttribute("TelekinesisAnchored", true) count = count + 1 end end notify("📌 Anclaje Masivo", "Se anclaron " .. count .. " objetos", 2) end local function mostrarPanel() if isMobile then notify( "📱 CONTROLES MÓVIL", "🎯 Puntero azul arrastrable\n✋ Agarrar/Soltar\n🔥 Lanzar\n📌 Anclar\n📏➖➕ Distancia\n⬆️⬇️ Fuerza", 10 ) else notify( "⌨️ CONTROLES PC", "🖱️ Click = Agarrar/Soltar\n🔥 F = Lanzar\n🔀 Q/E = Acercar/Alejar\n📌 R = Anclar\n🧲 T = Modo Imán\n🔄 C = Rotar\n⬇️ Z = -Fuerza\n⬆️ X = +Fuerza", 12 ) end end -- [[ CONTROLES MÓVIL - SOLO BOTONES ]] btnGrab.MouseButton1Click:Connect(function() if scriptActive then agarrarOSoltar() end end) btnThrow.MouseButton1Click:Connect(function() if scriptActive then lanzar() end end) btnAnchor.MouseButton1Click:Connect(function() if scriptActive then alternarAnclado() end end) -- MOVIMIENTO SUAVE DE DISTANCIA (VELOCIDAD 0.8) btnClose.InputBegan:Connect(function(input) if input.UserInputType.Name:find("Touch") or input.UserInputType.Name:find("Mouse") then holdClose = true end end) btnClose.InputEnded:Connect(function() holdClose = false end) btnFar.InputBegan:Connect(function(input) if input.UserInputType.Name:find("Touch") or input.UserInputType.Name:find("Mouse") then holdFar = true end end) btnFar.InputEnded:Connect(function() holdFar = false end) btnFUp.MouseButton1Click:Connect(function() if not scriptActive then return end fuerzaLanzamiento = math.min(fuerzaLanzamientoMax, fuerzaLanzamiento + 200) notify("⬆️ Potencia", "Fuerza: "..fuerzaLanzamiento, 0.5) end) btnFDown.MouseButton1Click:Connect(function() if not scriptActive then return end fuerzaLanzamiento = math.max(fuerzaLanzamientoMin, fuerzaLanzamiento - 200) notify("⬇️ Potencia", "Fuerza: "..fuerzaLanzamiento, 0.5) end) btnHide.MouseButton1Click:Connect(function() if scriptActive then buttonContainer.Visible = false fakePointer.Visible = false desactivarScript() local showBtn = crearBoton("ShowBtn", btnHide.Position, "👁️", Color3.new(0,0,0)) showBtn.BackgroundTransparency = 0.7 showBtn.Parent = mobileGui showBtn.MouseButton1Click:Connect(function() buttonContainer.Visible = true fakePointer.Visible = true showBtn:Destroy() activarScript() end) end end) -- [[ INPUT CONNECTIONS PC ]] _G.inputConnection = UIS.InputBegan:Connect(function(input, gpe) if gpe then return end if not scriptActive then return end if isMobile then return end if input.UserInputType == Enum.UserInputType.Keyboard then if rotationMode then if input.KeyCode == Enum.KeyCode.C then alternarModoRotacion() end return end if input.KeyCode == Enum.KeyCode.Q then holdQ = true elseif input.KeyCode == Enum.KeyCode.E then holdE = true elseif input.KeyCode == Enum.KeyCode.R then if imanActivo then anclarMasivoIman() else alternarAnclado() end elseif input.KeyCode == Enum.KeyCode.F then lanzar() elseif input.KeyCode == Enum.KeyCode.C then alternarModoRotacion() elseif input.KeyCode == Enum.KeyCode.T then if holding then notify("❌ No disponible", "Suelta el objeto para activar el imán", 2) return end imanActivo = not imanActivo if not imanActivo then restaurarPropiedadesOriginales() gravityBackup = {} end notify( imanActivo and "🧲 Modo Imán ACTIVADO" or "🧲 Modo Imán DESACTIVADO", "Atrae solo piezas sueltas en el círculo azul", 2 ) elseif input.KeyCode == Enum.KeyCode.Delete then desactivarScript() elseif input.KeyCode == Enum.KeyCode.LeftControl or input.KeyCode == Enum.KeyCode.RightControl then mostrarPanel() elseif input.KeyCode == Enum.KeyCode.Z then if imanActivo then fuerzaIman = math.max(fuerzaImanMin, fuerzaIman - 25) notify("🧲 Fuerza Imán", "↓ " .. math.floor(fuerzaIman), 1) else fuerzaLanzamiento = math.max(fuerzaLanzamientoMin, fuerzaLanzamiento - 100) notify("🎯 Fuerza Lanzamiento", "↓ " .. math.floor(fuerzaLanzamiento), 1) end elseif input.KeyCode == Enum.KeyCode.X then if imanActivo then fuerzaIman = math.min(fuerzaImanMax, fuerzaIman + 25) notify("🧲 Fuerza Imán", "↑ " .. math.floor(fuerzaIman), 1) else fuerzaLanzamiento = math.min(fuerzaLanzamientoMax, fuerzaLanzamiento + 100) notify("🎯 Fuerza Lanzamiento", "↑ " .. math.floor(fuerzaLanzamiento), 1) end end end end) _G.inputConnection2 = UIS.InputBegan:Connect(function(input, gpe) if gpe then return end if not scriptActive then return end if not isMobile then return end if input.UserInputType == Enum.UserInputType.Keyboard then if input.KeyCode == Enum.KeyCode.Delete then desactivarScript() end end end) _G.inputEndConnection = UIS.InputEnded:Connect(function(input) if not scriptActive then return end if rotationMode then return end if isMobile then return end if input.UserInputType == Enum.UserInputType.Keyboard then if input.KeyCode == Enum.KeyCode.Q then holdQ = false elseif input.KeyCode == Enum.KeyCode.E then holdE = false end end end) -- [[ RENDER STEPPED ]] _G.renderConnection = run.RenderStepped:Connect(function() if not scriptActive then return end if imanActivo and not holding then highlightHolding.Adornee = nil highlightLooking.Adornee = nil else if holding and target then highlightHolding.OutlineColor = Color3.fromRGB(0, 255, 0) highlightHolding.FillColor = Color3.fromRGB(0, 255, 0) highlightHolding.Adornee = target highlightLooking.Adornee = nil elseif not holding then local rayInfo = getPointInfo() local hit = workspace:FindPartOnRayWithIgnoreList(rayInfo, {player.Character}) if hit and hit:IsA("BasePart") and not hit.Anchored and not esParteDePersonaje(hit) then highlightLooking.OutlineColor = Color3.fromRGB(0, 170, 255) highlightLooking.FillColor = Color3.fromRGB(0, 170, 255) highlightLooking.Adornee = hit highlightHolding.Adornee = nil else highlightHolding.Adornee = nil highlightLooking.Adornee = nil end else highlightHolding.Adornee = nil highlightLooking.Adornee = nil end end if imanActivo and not rotationMode then local ray = camera:ScreenPointToRay(mouse.X, mouse.Y) local hit, pos, norm = workspace:FindPartOnRayWithIgnoreList(Ray.new(ray.Origin, ray.Direction * 1000), {player.Character}) if hit then surfacePos, surfaceNormal = lerpVec3(surfacePos,pos,0.35), lerpVec3(surfaceNormal,norm,0.35) else local defPos = ray.Origin + ray.Direction * 15 surfacePos, surfaceNormal = lerpVec3(surfacePos,defPos,0.15), lerpVec3(surfaceNormal,Vector3.new(0,1,0),0.15) end actualRadio = actualRadio + (radioIman - actualRadio) * 0.25 local fuerzaPercent = (fuerzaIman-fuerzaImanMin)/(fuerzaImanMax-fuerzaImanMin) local colorEscala = Color3.fromHSV(0.58 + fuerzaPercent*0.3, 1, 1) if usingDrawing then imancircle.Visible = true imancircle.Position = Vector2.new(camera:WorldToViewportPoint(surfacePos).X, camera:WorldToViewportPoint(surfacePos).Y) imancircle.Radius = actualRadio imancircle.Color = colorEscala else circleGui.Enabled = true circleGui.Size = UDim2.new(0,actualRadio*2,0,actualRadio*2) circleGui.CFrame = CFrame.new(surfacePos, surfacePos + camera.CFrame.LookVector) * CFrame.fromMatrix(Vector3.zero, surfaceNormal:Cross(Vector3.new(0,1,0)).Magnitude>0.01 and surfaceNormal:Cross(Vector3.new(0,1,0)).Unit or Vector3.new(1,0,0), surfaceNormal, -surfaceNormal:Cross(Vector3.new(1,0,0)).Unit) circleGui.Position = surfacePos circleImg.ImageColor3 = colorEscala end if guiVisible and not isMobile then fuerzaLabel.Visible = true fuerzaLabel.Text = "🧲 Fuerza: "..math.floor(fuerzaIman).."\n📏 Radio: "..math.floor(radioIman) fuerzaLabel.TextColor3 = colorEscala else fuerzaLabel.Visible = false end elseif not rotationMode then local fuerzaPercent = (fuerzaLanzamiento-fuerzaLanzamientoMin)/(fuerzaLanzamientoMax-fuerzaLanzamientoMin) local colorEscala = Color3.fromHSV(0.58 + fuerzaPercent*0.3, 1, 1) if usingDrawing then imancircle.Visible = false elseif circleGui then circleGui.Enabled = false end if guiVisible and not isMobile then fuerzaLabel.Visible = true fuerzaLabel.Text = "🎯 Lanzamiento: "..math.floor(fuerzaLanzamiento) fuerzaLabel.TextColor3 = colorEscala else fuerzaLabel.Visible = false end else if usingDrawing then imancircle.Visible = false elseif circleGui then circleGui.Enabled = false end fuerzaLabel.Visible = false end if rotationMode and holding and target then bloquearMovimientoPersonaje() if fixedCameraPosition and fixedCameraRotation then camera.CFrame = fixedCameraRotation + fixedCameraPosition end if fixedObjectPosition then positionLock.Velocity = Vector3.new(0, 0, 0) target.Position = fixedObjectPosition end local currentMouseX = mouse.X local currentMouseY = mouse.Y local mouseDeltaX = currentMouseX - lastMouseX local mouseDeltaY = currentMouseY - lastMouseY lastMouseX = currentMouseX lastMouseY = currentMouseY if math.abs(mouseDeltaX) > 0 or math.abs(mouseDeltaY) > 0 then local rotationX = CFrame.fromAxisAngle(Vector3.new(0, 1, 0), math.rad(mouseDeltaX * rotationSensitivity)) local rotationY = CFrame.fromAxisAngle(Vector3.new(1, 0, 0), math.rad(mouseDeltaY * rotationSensitivity)) if originalRotation then originalRotation = originalRotation * rotationX * rotationY gyro.CFrame = originalRotation + target.Position end end end -- MOVIMIENTO SUAVE CONSTANTE (VELOCIDAD 0.8) if holding and target and not rotationMode then if holdFar then holdDistance = math.min(500, holdDistance + 0.8) end if holdClose then holdDistance = math.max(2, holdDistance - 0.8) end end end) -- [[ HEARTBEAT ]] _G.heartbeatConnection = run.Heartbeat:Connect(function() if not scriptActive then return end if holding and target then if not anchoredWhileHolding and not rotationMode then local rayInfo = getPointInfo() local grabPos = rayInfo.Origin + rayInfo.Direction.Unit * holdDistance vel.Velocity = (grabPos - target.Position) * 5 if originalRotation then gyro.CFrame = originalRotation + target.Position end elseif rotationMode then vel.Velocity = Vector3.new(0, 0, 0) else vel.Velocity = Vector3.zero end end if imanActivo and not rotationMode then local centro, nuevosAtraidos = surfacePos, {} local fuerzaEscalada = fuerzaIman * (radioIman/30)^1.5 local nearby = workspace:GetPartBoundsInBox(CFrame.new(centro), Vector3.new(radioIman*2, radioIman*2, radioIman*2)) for _, obj in ipairs(nearby) do if obj:IsA("BasePart") and not obj.Anchored and not esParteDePersonaje(obj) and not tieneSoldaduraNoAnclada(obj) and obj.Transparency < 1 and obj.CanCollide and obj ~= target then local distancia = (obj.Position - centro).Magnitude if distancia <= radioIman then local dirFinal = (centro - obj.Position) local bv = obj:FindFirstChild("ImanBV") or Instance.new("BodyVelocity") bv.Name, bv.MaxForce, bv.P = "ImanBV", Vector3.new(1,1,1)*1e5, 15000 bv.Velocity = dirFinal.Unit * fuerzaEscalada bv.Parent = obj if not originalPhysicalProperties[obj] then originalPhysicalProperties[obj] = obj.CustomPhysicalProperties end if not gravityBackup[obj] then gravityBackup[obj] = obj.CustomPhysicalProperties end obj.CustomPhysicalProperties = PhysicalProperties.new(0.1, 0.3, 0.5, 1, 1) nuevosAtraidos[obj] = true end end end for obj in pairs(objetosIman) do if not nuevosAtraidos[obj] then if obj and obj:FindFirstChild("ImanBV") then obj.ImanBV:Destroy() end end end objetosIman = nuevosAtraidos else for obj in pairs(objetosIman) do if obj and obj:FindFirstChild("ImanBV") then obj.ImanBV:Destroy() end end restaurarPropiedadesOriginales() gravityBackup = {} objetosIman = {} end if not rotationMode then if imanActivo then if holdQ then radioIman = math.max(5, radioIman - 1.3) elseif holdE then radioIman = math.min(200, radioIman + 1.3) end else if holdQ then holdDistance = math.max(2, holdDistance - 0.4) elseif holdE then holdDistance = math.min(1000, holdDistance + 0.4) end end end end) -- [[ FIN DEL SCRIPT ]] print("✅ Telekinesis V3 Completo Mejorado: Móvil Optimizado + PC Completo")