Загрузка данных
-- BillCipherAI (Script в ServerScriptService)
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local TweenService = game:GetService("TweenService")
-- ═══════════════════════════════════════════
-- СОЗДАЁМ БИЛЛА ШИФРА
-- ═══════════════════════════════════════════
local function createBill()
local bill = Instance.new("Model")
bill.Name = "BillCipher"
-- Основное тело — жёлтый треугольник (симулируем через клин)
local body = Instance.new("WedgePart")
body.Name = "Body"
body.Size = Vector3.new(2, 3, 0.3)
body.BrickColor = BrickColor.new("Bright yellow")
body.Material = Enum.Material.Neon
body.Anchored = false
body.CanCollide = false
body.CastShadow = true
body.Parent = bill
-- Глаз (белый с чёрным зрачком)
local eye = Instance.new("SpherePartOperation") -- если нет CSG, используем шар
-- Fallback: обычный Part
local eyeWhite = Instance.new("Part")
eyeWhite.Name = "EyeWhite"
eyeWhite.Shape = Enum.PartType.Ball
eyeWhite.Size = Vector3.new(0.7, 0.7, 0.3)
eyeWhite.BrickColor = BrickColor.new("White")
eyeWhite.Material = Enum.Material.SmoothPlastic
eyeWhite.CanCollide = false
eyeWhite.Anchored = false
eyeWhite.Parent = bill
local pupil = Instance.new("Part")
pupil.Name = "Pupil"
pupil.Shape = Enum.PartType.Ball
pupil.Size = Vector3.new(0.35, 0.35, 0.3)
pupil.BrickColor = BrickColor.new("Black")
pupil.Material = Enum.Material.SmoothPlastic
pupil.CanCollide = false
pupil.Anchored = false
pupil.Parent = bill
-- Цилиндр (шляпа)
local hat = Instance.new("Part")
hat.Name = "Hat"
hat.Shape = Enum.PartType.Cylinder
hat.Size = Vector3.new(0.6, 1.2, 1.2)
hat.BrickColor = BrickColor.new("Black")
hat.Material = Enum.Material.SmoothPlastic
hat.CanCollide = false
hat.Anchored = false
hat.Parent = bill
-- Поля шляпы
local brim = Instance.new("Part")
brim.Name = "Brim"
brim.Shape = Enum.PartType.Cylinder
brim.Size = Vector3.new(0.2, 1.8, 1.8)
brim.BrickColor = BrickColor.new("Black")
brim.Material = Enum.Material.SmoothPlastic
brim.CanCollide = false
brim.Anchored = false
brim.Parent = bill
-- Руки (тонкие палки)
local function createArm(side)
local arm = Instance.new("Part")
arm.Name = "Arm" .. side
arm.Size = Vector3.new(0.15, 1.4, 0.15)
arm.BrickColor = BrickColor.new("Bright yellow")
arm.Material = Enum.Material.Neon
arm.CanCollide = false
arm.Anchored = false
arm.Parent = bill
-- Перчатка (белый шар на конце)
local glove = Instance.new("Part")
glove.Name = "Glove" .. side
glove.Shape = Enum.PartType.Ball
glove.Size = Vector3.new(0.3, 0.3, 0.3)
glove.BrickColor = BrickColor.new("White")
glove.Material = Enum.Material.SmoothPlastic
glove.CanCollide = false
glove.Anchored = false
glove.Parent = bill
return arm, glove
end
local armL, gloveL = createArm("L")
local armR, gloveR = createArm("R")
-- Ноги
local function createLeg(side)
local leg = Instance.new("Part")
leg.Name = "Leg" .. side
leg.Size = Vector3.new(0.15, 1.0, 0.15)
leg.BrickColor = BrickColor.new("Black")
leg.Material = Enum.Material.SmoothPlastic
leg.CanCollide = false
leg.Anchored = false
leg.Parent = bill
local shoe = Instance.new("Part")
shoe.Name = "Shoe" .. side
shoe.Size = Vector3.new(0.4, 0.2, 0.5)
shoe.BrickColor = BrickColor.new("Black")
shoe.Material = Enum.Material.SmoothPlastic
shoe.CanCollide = false
shoe.Anchored = false
shoe.Parent = bill
return leg, shoe
end
local legL, shoeL = createLeg("L")
local legR, shoeR = createLeg("R")
-- Bow tie (галстук-бабочка)
local bowtie = Instance.new("Part")
bowtie.Name = "Bowtie"
bowtie.Size = Vector3.new(0.5, 0.2, 0.1)
bowtie.BrickColor = BrickColor.new("Black")
bowtie.Material = Enum.Material.SmoothPlastic
bowtie.CanCollide = false
bowtie.Anchored = false
bowtie.Parent = bill
-- PrimaryPart = тело
bill.PrimaryPart = body
-- Сварка всех частей к телу через WeldConstraints
local function weld(part0, part1, offset)
local wc = Instance.new("WeldConstraint")
wc.Part0 = part0
wc.Part1 = part1
wc.Parent = part0
-- Задаём относительную позицию через CFrame перед сваркой
part1.CFrame = part0.CFrame * offset
end
-- Позиционируем части относительно тела
body.CFrame = CFrame.new(0, 5, 0)
eyeWhite.CFrame = body.CFrame * CFrame.new(0, 0.3, -0.2)
pupil.CFrame = body.CFrame * CFrame.new(0, 0.3, -0.35)
hat.CFrame = body.CFrame * CFrame.new(0, 1.8, 0) * CFrame.Angles(0, 0, math.rad(90))
brim.CFrame = body.CFrame * CFrame.new(0, 1.45, 0) * CFrame.Angles(0, 0, math.rad(90))
bowtie.CFrame = body.CFrame * CFrame.new(0, -0.8, -0.2)
armL.CFrame = body.CFrame * CFrame.new(-1.2, 0, 0) * CFrame.Angles(0, 0, math.rad(30))
armR.CFrame = body.CFrame * CFrame.new( 1.2, 0, 0) * CFrame.Angles(0, 0, math.rad(-30))
gloveL.CFrame = body.CFrame * CFrame.new(-1.9, -0.6, 0)
gloveR.CFrame = body.CFrame * CFrame.new( 1.9, -0.6, 0)
legL.CFrame = body.CFrame * CFrame.new(-0.4, -2.0, 0)
legR.CFrame = body.CFrame * CFrame.new( 0.4, -2.0, 0)
shoeL.CFrame = body.CFrame * CFrame.new(-0.4, -2.55, 0.1)
shoeR.CFrame = body.CFrame * CFrame.new( 0.4, -2.55, 0.1)
-- Свариваем
local parts = {eyeWhite, pupil, hat, brim, bowtie, armL, armR, gloveL, gloveR, legL, legR, shoeL, shoeR}
for _, p in ipairs(parts) do
local wc = Instance.new("WeldConstraint")
wc.Part0 = body
wc.Part1 = p
wc.Parent = body
end
bill.Parent = workspace
return bill
end
-- ═══════════════════════════════════════════
-- ХИЖИНА ЧУДЕС — базовая структура
-- ═══════════════════════════════════════════
local function buildCabin()
local cabin = Instance.new("Model")
cabin.Name = "MysteryShack"
local WOOD = BrickColor.new("Reddish brown")
local ROOF = BrickColor.new("Dark orange")
local FLOOR_MAT = Enum.Material.WoodPlanks
-- Пол
local floor = Instance.new("Part")
floor.Name = "Floor"
floor.Size = Vector3.new(30, 1, 20)
floor.CFrame = CFrame.new(0, 0.5, 0)
floor.BrickColor = WOOD
floor.Material = FLOOR_MAT
floor.Anchored = true
floor.Parent = cabin
-- Стены
local wallsData = {
-- {name, size, position, rotation}
{"WallFront", Vector3.new(30, 12, 1), CFrame.new(0, 6.5, -10)},
{"WallBack", Vector3.new(30, 12, 1), CFrame.new(0, 6.5, 10)},
{"WallLeft", Vector3.new(1, 12, 20), CFrame.new(-15, 6.5, 0)},
{"WallRight", Vector3.new(1, 12, 20), CFrame.new( 15, 6.5, 0)},
}
for _, data in ipairs(wallsData) do
local wall = Instance.new("Part")
wall.Name = data[1]
wall.Size = data[2]
wall.CFrame = data[3]
wall.BrickColor = WOOD
wall.Material = FLOOR_MAT
wall.Anchored = true
wall.Parent = cabin
end
-- Потолок
local ceiling = Instance.new("Part")
ceiling.Size = Vector3.new(30, 1, 20)
ceiling.CFrame = CFrame.new(0, 13, 0)
ceiling.BrickColor = WOOD
ceiling.Material = FLOOR_MAT
ceiling.Anchored = true
ceiling.Name = "Ceiling"
ceiling.Parent = cabin
-- Крыша (два ската через WedgePart)
local roofL = Instance.new("WedgePart")
roofL.Size = Vector3.new(30, 5, 12)
roofL.CFrame = CFrame.new(0, 16.5, -4) * CFrame.Angles(0, 0, math.rad(0))
roofL.BrickColor = ROOF
roofL.Material = Enum.Material.SmoothPlastic
roofL.Anchored = true
roofL.Parent = cabin
local roofR = Instance.new("WedgePart")
roofR.Size = Vector3.new(30, 5, 12)
roofR.CFrame = CFrame.new(0, 16.5, 4) * CFrame.Angles(0, math.rad(180), 0)
roofR.BrickColor = ROOF
roofR.Material = Enum.Material.SmoothPlastic
roofR.Anchored = true
roofR.Parent = cabin
-- Дверной проём в передней стене (вырезаем через PartOperation если доступно, иначе делаем две колонны)
-- Простой вариант: два куска стены по бокам от двери
workspace.WallFront and (workspace.WallFront:Destroy()) -- если уже есть
-- Боковые куски передней стены (дверь 4x8 по центру)
local frontLeft = Instance.new("Part")
frontLeft.Size = Vector3.new(13, 12, 1)
frontLeft.CFrame = CFrame.new(-8.5, 6.5, -10)
frontLeft.BrickColor = WOOD
frontLeft.Material = FLOOR_MAT
frontLeft.Anchored = true
frontLeft.Parent = cabin
local frontRight = Instance.new("Part")
frontRight.Size = Vector3.new(13, 12, 1)
frontRight.CFrame = CFrame.new(8.5, 6.5, -10)
frontRight.BrickColor = WOOD
frontRight.Material = FLOOR_MAT
frontRight.Anchored = true
frontRight.Parent = cabin
local frontTop = Instance.new("Part")
frontTop.Size = Vector3.new(4, 4, 1)
frontTop.CFrame = CFrame.new(0, 11, -10)
frontTop.BrickColor = WOOD
frontTop.Material = FLOOR_MAT
frontTop.Anchored = true
frontTop.Parent = cabin
-- Мебель: прилавок
local counter = Instance.new("Part")
counter.Size = Vector3.new(8, 3, 2)
counter.CFrame = CFrame.new(0, 2.5, 5)
counter.BrickColor = WOOD
counter.Material = FLOOR_MAT
counter.Anchored = true
counter.Parent = cabin
-- Полки
for i = 1, 3 do
local shelf = Instance.new("Part")
shelf.Size = Vector3.new(10, 0.3, 2)
shelf.CFrame = CFrame.new(-14, 3 + i * 2.5, 0)
shelf.BrickColor = WOOD
shelf.Material = FLOOR_MAT
shelf.Anchored = true
shelf.Parent = cabin
end
-- Знак "Mystery Shack"
local sign = Instance.new("Part")
sign.Size = Vector3.new(12, 3, 0.3)
sign.CFrame = CFrame.new(0, 14, -10.2)
sign.BrickColor = BrickColor.new("Bright yellow")
sign.Material = Enum.Material.SmoothPlastic
sign.Anchored = true
sign.Parent = cabin
local signGui = Instance.new("SurfaceGui")
signGui.Face = Enum.NormalId.Front
signGui.Parent = sign
local signLabel = Instance.new("TextLabel")
signLabel.Size = UDim2.new(1, 0, 1, 0)
signLabel.BackgroundTransparency = 1
signLabel.Text = "MYSTERY SHACK"
signLabel.TextColor3 = Color3.fromRGB(50, 20, 0)
signLabel.TextScaled = true
signLabel.Font = Enum.Font.Antique
signLabel.Parent = signGui
-- Лесной фон снаружи (зелёная плоскость)
local ground = Instance.new("Part")
ground.Size = Vector3.new(500, 1, 500)
ground.CFrame = CFrame.new(0, -0.5, 0)
ground.BrickColor = BrickColor.new("Forest green")
ground.Material = Enum.Material.Grass
ground.Anchored = true
ground.Parent = cabin
-- Несколько деревьев
local function makeTree(x, z)
local trunk = Instance.new("Part")
trunk.Shape = Enum.PartType.Cylinder
trunk.Size = Vector3.new(8, 1.5, 1.5)
trunk.CFrame = CFrame.new(x, 4, z) * CFrame.Angles(0, 0, math.rad(90))
trunk.BrickColor = BrickColor.new("Reddish brown")
trunk.Material = Enum.Material.SmoothPlastic
trunk.Anchored = true
trunk.Parent = cabin
local leaves = Instance.new("Part")
leaves.Shape = Enum.PartType.Ball
leaves.Size = Vector3.new(8, 8, 8)
leaves.CFrame = CFrame.new(x, 9, z)
leaves.BrickColor = BrickColor.new("Forest green")
leaves.Material = Enum.Material.Grass
leaves.Anchored = true
leaves.Parent = cabin
end
local treePositions = {
{-30, -25}, {30, -25}, {-40, 0}, {40, 0},
{-35, 20}, {35, 20}, {-25, 30}, {25, 30},
{-50, -15}, {50, -15}
}
for _, pos in ipairs(treePositions) do
makeTree(pos[1], pos[2])
end
cabin.Parent = workspace
return cabin
end
-- ═══════════════════════════════════════════
-- ЛОГИКА ПРЕСЛЕДОВАНИЯ
-- ═══════════════════════════════════════════
local CHASE_SPEED = 14 -- studs/sec
local TELEPORT_DIST = 60 -- дальше этого Билл телепортируется ближе
local JUMPSCARE_DIST = 4 -- дистанция крика
local PATROL_RADIUS = 8 -- радиус патруля когда игроков нет
local ROTATION_SPEED = 5 -- скорость поворота к игроку
-- Звуки (ID из Roblox Asset Library — публичные)
local LAUGH_SOUND_ID = "rbxassetid://5615086548" -- смех Билла (можно заменить)
local SCREAM_SOUND_ID = "rbxassetid://1448796680" -- крик
local billModel = nil
local jumpscareCooldown = {} -- {[player] = timestamp}
local function playSound(soundId, parent)
local s = Instance.new("Sound")
s.SoundId = soundId
s.Volume = 1
s.RollOffMaxDistance = 60
s.Parent = parent or workspace
s:Play()
game:GetService("Debris"):AddItem(s, 5)
end
local function getClosestPlayer(from)
local closest, closestDist = nil, math.huge
for _, p in ipairs(Players:GetPlayers()) do
local char = p.Character
if char then
local root = char:FindFirstChild("HumanoidRootPart")
if root then
local dist = (root.Position - from).Magnitude
if dist < closestDist then
closest = p
closestDist = dist
end
end
end
end
return closest, closestDist
end
local function jumpScare(player)
local now = tick()
if jumpscareCooldown[player] and (now - jumpscareCooldown[player]) < 10 then return end
jumpscareCooldown[player] = now
-- Отправляем RemoteEvent игроку для эффекта экрана
local re = game:GetService("ReplicatedStorage"):FindFirstChild("BillJumpScare")
if re then
re:FireClient(player)
end
end
-- ═══════════════════════════════════════════
-- АНИМАЦИЯ БИЛЛА (вращение + покачивание)
-- ═══════════════════════════════════════════
local function animateBill(bill, dt, time)
if not bill or not bill.PrimaryPart then return end
-- Левитация
local hover = math.sin(time * 2) * 0.3
local currentCF = bill.PrimaryPart.CFrame
bill:SetPrimaryPartCFrame(
CFrame.new(currentCF.X, 5 + hover, currentCF.Z) *
CFrame.Angles(0, currentCF:ToEulerAnglesYXZ(), 0)
)
end
-- ═══════════════════════════════════════════
-- JUMPSSCARE REMOTE EVENT
-- ═══════════════════════════════════════════
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local jumpScareRE = Instance.new("RemoteEvent")
jumpScareRE.Name = "BillJumpScare"
jumpScareRE.Parent = ReplicatedStorage
-- ═══════════════════════════════════════════
-- MAIN LOOP
-- ═══════════════════════════════════════════
-- Строим хижину и создаём Билла при старте
buildCabin()
wait(2) -- ждём загрузки карты
billModel = createBill()
-- Ставим Билла в случайное место снаружи
if billModel and billModel.PrimaryPart then
billModel:SetPrimaryPartCFrame(CFrame.new(40, 5, 40))
end
local lastLaugh = 0
local time = 0
RunService.Heartbeat:Connect(function(dt)
time = time + dt
if not billModel or not billModel.PrimaryPart then return end
local billRoot = billModel.PrimaryPart
local billPos = billRoot.Position
local target, dist = getClosestPlayer(billPos)
if target then
local targetChar = target.Character
local targetRoot = targetChar and targetChar:FindFirstChild("HumanoidRootPart")
if targetRoot then
local targetPos = targetRoot.Position
-- Телепорт если слишком далеко (чтобы не терять игрока)
if dist > TELEPORT_DIST then
local offset = Vector3.new(math.random(-15, 15), 0, math.random(-15, 15))
billModel:SetPrimaryPartCFrame(CFrame.new(targetPos + offset + Vector3.new(0, 5, 0)))
return
end
-- Движение к игроку
local direction = (targetPos - billPos)
direction = Vector3.new(direction.X, 0, direction.Z).Unit
local newPos = billPos + direction * CHASE_SPEED * dt
newPos = Vector3.new(newPos.X, 5 + math.sin(time * 2) * 0.3, newPos.Z)
-- Поворот к игроку
local lookAt = CFrame.lookAt(newPos, Vector3.new(targetPos.X, newPos.Y, targetPos.Z))
billModel:SetPrimaryPartCFrame(lookAt)
-- Смех каждые 8 секунд
if tick() - lastLaugh > 8 then
lastLaugh = tick()
playSound(LAUGH_SOUND_ID, billRoot)
end
-- Джамп-скер при близком контакте
if dist < JUMPSCARE_DIST then
jumpScare(target)
playSound(SCREAM_SOUND_ID, billRoot)
-- Отталкиваем игрока
local humanoid = targetChar:FindFirstChildOfClass("Humanoid")
local hrp = targetChar:FindFirstChild("HumanoidRootPart")
if hrp then
hrp.Velocity = (targetPos - billPos).Unit * 50 + Vector3.new(0, 20, 0)
end
end
end
else
-- Патруль когда игроков нет
local angle = time * 0.5
local patrolPos = Vector3.new(
math.sin(angle) * PATROL_RADIUS,
5 + math.sin(time * 2) * 0.3,
math.cos(angle) * PATROL_RADIUS
)
local lookDir = Vector3.new(math.cos(angle), 0, -math.sin(angle))
billModel:SetPrimaryPartCFrame(
CFrame.new(patrolPos) * CFrame.fromMatrix(Vector3.zero, lookDir:Cross(Vector3.yAxis) * -1, Vector3.yAxis, -lookDir)
)
end
end)