-- Cherry's Club | The Nightmare Locust (V22 - Smooth & Reactive) local Players = game:GetService("Players") local LocalPlayer = Players.LocalPlayer local RunService = game:GetService("RunService") local SoundService = game:GetService("SoundService") local MODEL_ID = "85434241672934" local currentModel = nil local rootPart = nil local bones = {} local walkPhase = 0 local twitchPhase = 0 local breathPhase = 0 local rayParams = RaycastParams.new() -- ============================================================ -- AUDIO -- ============================================================ local AUDIO_URL = "https://raw.githubusercontent.com/michineitorxd3000-coder/idk-bro-locust/main/Locustadiotrack.mp3.mp3" local FOLDER_NAME = "LocustAudio" local FILE_NAME = "Locustadiotrack.mp3" local FILE_PATH = FOLDER_NAME .. "/" .. FILE_NAME local function setupAudio() if not writefile or not isfolder or not isfile or not getcustomasset then return "rbxassetid://131961136" end if not isfolder(FOLDER_NAME) then makefolder(FOLDER_NAME) end if not isfile(FILE_PATH) then local success, response = pcall(function() return game:HttpGet(AUDIO_URL) end) if success and response then writefile(FILE_PATH, response) else return "rbxassetid://131961136" end end local assetSuccess, assetId = pcall(function() return getcustomasset(FILE_PATH) end) return assetSuccess and assetId or "rbxassetid://131961136" end local customSoundId = setupAudio() local screechSound = Instance.new("Sound") screechSound.SoundId = customSoundId screechSound.Volume = 3 screechSound.Pitch = 0.8 screechSound.RollOffMaxDistance = 120 screechSound.Parent = SoundService local function playScreech() if not screechSound.IsPlaying then task.delay(math.random(0, 50) / 100, function() if not screechSound.IsPlaying then screechSound:Play() end end) end end -- ============================================================ -- SPAWN (True Morph) -- ============================================================ local function spawnModel() if currentModel then currentModel:Destroy(); currentModel = nil end bones = {} local char = LocalPlayer.Character local hrp = char and char:FindFirstChild("HumanoidRootPart") local hum = char and char:FindFirstChildOfClass("Humanoid") if not hrp or not hum then return end local animateScript = char:FindFirstChild("Animate") if animateScript then animateScript:Destroy() end local animator = hum:FindFirstChildOfClass("Animator") if animator then for _, track in ipairs(animator:GetPlayingAnimationTracks()) do track:Stop() end end -- Ocultar y destruir accesorios for _, obj in ipairs(char:GetChildren()) do if obj:IsA("Accessory") or obj:IsA("Shirt") or obj:IsA("Pants") or obj:IsA("ShirtGraphic") then obj:Destroy() end end local success, model = pcall(function() return game:GetObjects("rbxassetid://" .. MODEL_ID)[1] end) if not success or not model then return end for _, obj in ipairs(model:GetDescendants()) do if obj:IsA("BasePart") then obj.Anchored = true obj.CanCollide = false elseif obj:IsA("Script") or obj:IsA("LocalScript") then obj:Destroy() end end model.Name = "NightmareLocust" model.Parent = workspace currentModel = model model:ScaleTo(0.05) rootPart = model:FindFirstChild("RootPart", true) or model:FindFirstChildWhichIsA("BasePart") if not rootPart then return end model.PrimaryPart = rootPart for _, obj in ipairs(model:GetDescendants()) do if obj:IsA("Bone") then bones[obj.Name] = { bone = obj, restCFrame = obj.CFrame } end end rayParams.FilterDescendantsInstances = { char, currentModel } rayParams.FilterType = Enum.RaycastFilterType.Exclude playScreech() end -- ============================================================ -- LOOP PRINCIPAL -- ============================================================ RunService.RenderStepped:Connect(function(dt) if not currentModel or not rootPart then return end local char = LocalPlayer.Character local hrp = char and char:FindFirstChild("HumanoidRootPart") local hum = char and char:FindFirstChildOfClass("Humanoid") if not hrp or not hum then return end -- Invisibilidad for _, part in ipairs(char:GetDescendants()) do if part:IsA("BasePart") and part.Name ~= "HumanoidRootPart" then part.Transparency = 1 part.LocalTransparencyModifier = 1 end end local speed = hum.MoveDirection.Magnitude * hum.WalkSpeed local moving = speed > 0.1 -- Variables de reacción local lightReaction = 0 local isScaredOfLight = false if moving then walkPhase = walkPhase + dt * (speed * 0.25) -- Más lento = más fluido twitchPhase = twitchPhase + dt * 15 breathPhase = breathPhase + dt * 4 if math.random() > 0.98 then playScreech() end else walkPhase = 0 breathPhase = breathPhase + dt * 1.5 twitchPhase = twitchPhase + dt * (math.random() > 0.9 and 20 or 2) if math.random() > 0.995 then playScreech() end end -- ============================================================ -- REACCIÓN A LA LUZ (Si hay una linterna cerca, se asusta) -- ============================================================ for _, obj in ipairs(workspace:GetDescendants()) do if obj:IsA("SpotLight") or obj:IsA("PointLight") then if obj.Enabled and obj.Brightness > 1 then local dist = (obj.Parent.Position - hrp.Position).Magnitude if dist < 25 then -- Si la luz está a menos de 25 studs isScaredOfLight = true lightReaction = math.clamp(1 - (dist / 25), 0, 1) -- Más cerca = más reacción end end end end if isScaredOfLight and math.random() > 0.9 then playScreech() -- Chilla si le da la luz end -- ============================================================ -- MATEMÁTICAS DE SUELO (Sin rotar hacia adelante) -- ============================================================ local baseOffset = -3.0 -- Subimos un poco el cuerpo para que no toque el suelo local rayOrigin = hrp.Position local floorHit = workspace:Raycast(rayOrigin, Vector3.new(0, -10, 0), rayParams) if floorHit then local distanceToFloor = (hrp.Position.Y - floorHit.Position.Y) baseOffset = -distanceToFloor + 0.5 end local ceilingRay = workspace:Raycast(hrp.Position + Vector3.new(0, 2, 0), Vector3.new(0, 6, 0), rayParams) if ceilingRay then baseOffset = baseOffset - 0.5 end -- SWAY (Balanceo natural del cuerpo) local sway = moving and math.sin(walkPhase) * math.rad(3) or 0 local bob = moving and ((math.sin(walkPhase * 2) * 0.2) - 0.2) or 0 rootPart.CFrame = hrp.CFrame * CFrame.new(0, baseOffset + bob, 0) local function applyBone(name, rotOffset) local bData = bones[name] if bData then bData.bone.CFrame = bData.restCFrame * rotOffset end end -- ============================================================ -- POSTURA (Menos inclinado, más fluido) -- ============================================================ local breath = math.sin(breathPhase) * math.rad(2) -- Si tiene miedo a la luz, se echa hacia atrás. Si no, camina normal. local huntPose = 0 if isScaredOfLight then huntPose = math.rad(15) * lightReaction -- Se arquea hacia atrás else huntPose = moving and math.rad(-15) or math.rad(-5) -- Menos inclinado end -- Aplicamos Sway a la columna applyBone("spine", CFrame.Angles(huntPose + sway + breath, 0, 0)) applyBone("spine.001", CFrame.Angles(sway + breath, 0, 0)) applyBone("spine.002", CFrame.Angles(sway, 0, 0)) -- Joroba suave local hunch = isScaredOfLight and math.rad(5) or math.rad(-10) applyBone("spine.003", CFrame.Angles(hunch + breath, 0, 0)) applyBone("spine.004", CFrame.Angles(hunch, 0, 0)) applyBone("spine.005", CFrame.Angles(hunch, 0, 0)) -- CABEZA (Mira a los lados suavemente) local headTwitch = math.sin(twitchPhase * 1.5) * math.rad(8) local neckTwitch = math.cos(twitchPhase * 0.8) * math.rad(4) applyBone("spine.006", CFrame.Angles(hunch + neckTwitch, headTwitch, 0)) -- ============================================================ -- PIERNAS (Animación de paso suave, sin rigidez) -- ============================================================ if moving then local function getLegRotations(phase) -- Usamos una onda senoidal más suave local s = math.sin(phase) local c = math.cos(phase) -- Pasos más largos y suaves local thighRotX = s * math.rad(45) -- La rodilla se dobla suavemente local kneeRotX = (s > 0) and -(s * math.rad(60)) or -math.rad(15) -- Un pequeño balanceo lateral en la cadera (Sway de piernas) local thighRotZ = c * math.rad(5) return CFrame.Angles(thighRotX, 0, thighRotZ), CFrame.Angles(kneeRotX, 0, 0) end local rThigh, rKnee = getLegRotations(walkPhase) local lThigh, lKnee = getLegRotations(walkPhase + math.pi) applyBone("thigh.R", rThigh) applyBone("thigh.L", lThigh) applyBone("shin.R", rKnee) applyBone("shin.L", lKnee) local function getFootAngle(phase) local s = math.sin(phase) return CFrame.Angles(s * math.rad(20), 0, 0) end applyBone("foot.R", getFootAngle(walkPhase)) applyBone("foot.L", getFootAngle(walkPhase + math.pi)) else -- Quieto (Respirando y con miedo a la luz) local idleThigh = isScaredOfLight and math.rad(10) or math.rad(20) applyBone("thigh.R", CFrame.Angles(idleThigh, 0, 0)) applyBone("thigh.L", CFrame.Angles(idleThigh, 0, 0)) applyBone("shin.R", CFrame.Angles(-math.rad(30), 0, 0)) applyBone("shin.L", CFrame.Angles(-math.rad(30), 0, 0)) applyBone("foot.R", CFrame.Angles(math.rad(10), 0, 0)) applyBone("foot.L", CFrame.Angles(math.rad(10), 0, 0)) end -- ============================================================ -- BRAZOS (Fluidos y con Raycast) -- ============================================================ local armSwing = moving and math.sin(walkPhase + math.pi) * math.rad(15) or 0 local tremble = math.sin(twitchPhase) * math.rad(1.5) -- Si tiene miedo a la luz, se cubre la cara con los brazos local coverFace = isScaredOfLight and math.rad(90) * lightReaction or 0 local armL = CFrame.Angles(armSwing + tremble + math.rad(5) + coverFace, 0, math.rad(5)) local armR = CFrame.Angles(-armSwing - tremble + math.rad(5) + coverFace, 0, math.rad(-5)) local shoulderR = bones["shoulder.R"] and bones["shoulder.R"].bone.WorldPosition local shoulderL = bones["shoulder.L"] and bones["shoulder.L"].bone.WorldPosition if shoulderR then local hitR = workspace:Raycast(shoulderR, rootPart.CFrame.RightVector * 8, rayParams) if hitR then local lookDir = (hitR.Position - shoulderR).Unit armR = CFrame.lookAt(Vector3.new(0,0,0), lookDir) * CFrame.Angles(math.rad(-90), 0, 0) end end if shoulderL then local hitL = workspace:Raycast(shoulderL, -rootPart.CFrame.RightVector * 8, rayParams) if hitL then local lookDir = (hitL.Position - shoulderL).Unit armL = CFrame.lookAt(Vector3.new(0,0,0), lookDir) * CFrame.Angles(math.rad(-90), 0, 0) end end applyBone("upper_arm.R", armR) applyBone("upper_arm.L", armL) end) LocalPlayer.CharacterAdded:Connect(function() task.wait(1) spawnModel() end) task.wait(1) spawnModel()