Roblox · Дополнительное

Дверь с кодом

У двери кодовая панель: E — открывается окно с кнопками 0–9. Набрал верный код — «ОТКРЫТО», дверь уезжает и через 4 секунды закрывается. Код хранится на сервере — подсмотреть его нельзя.

Структура

Синим — что нужно создать.

Workspace
└─ CodeDoor (Model)
   ├─ Door (Part)
   ├─ Keypad (Part) — панель
   │  └─ ProximityPrompt (ProximityPrompt) — «Ввести код»
   ├─ TryCode (RemoteFunction) — клиент спрашивает — сервер проверяет
   ├─ Configuration (Configuration) — OpenTime
   └─ CodeDoorServer (Script) — код — в первой строке
StarterGui
└─ KeypadGui (ScreenGui) — ResetOnSpawn выкл.
   └─ Frame (Frame) — Visible выкл.
      ├─ Display (TextLabel) — экранчик
      ├─ Grid (Frame) — кнопки создаёт скрипт
      │  └─ UIGridLayout (UIGridLayout) — SortOrder = LayoutOrder
      └─ Close (TextButton) — крестик
StarterPlayer → StarterPlayerScripts
└─ KeypadLocal (LocalScript)

Шаги

  1. Модель «CodeDoor»: Door, панель «Keypad» с ProximityPrompt, RemoteFunction «TryCode», Script «CodeDoorServer». Код — в его первой строке: CODE = "1234".
  2. Почему код в скрипте: текст серверного скрипта игрокам не отправляется. Значения в StringValue или атрибутах игрок может прочитать — там код хранить нельзя.
  3. StarterGui → ScreenGui «KeypadGui» → Frame (Visible выкл.) с TextLabel «Display», Frame «Grid» (внутри UIGridLayout) и TextButton «Close». 12 кнопок скрипт создаёт сам.
  4. StarterPlayerScripts → LocalScript «KeypadLocal»: ловит нажатие E у любой панели «Keypad» (ProximityPromptService.PromptTriggered) — один скрипт на все кодовые двери.
  5. Сервер проверяет: не чаще двух попыток в секунду, игрок рядом с дверью, код совпал.

Скрипты

CodeDoorServer

Где: Workspace → CodeDoor · Script
Зачем: Проверка кода и открытие.

-- плавное движение
local TS = game:GetService("TweenService")
-- модель двери с кодом
local model = script.Parent
-- дверь
local door = model:WaitForChild("Door")
-- игрок присылает код
local tryCode = model:WaitForChild("TryCode")
-- настройки
local config = model:WaitForChild("Configuration")
-- код двери — здесь игроки его не увидят: текст серверного скрипта им не отправляется
local CODE = "1234"
-- закрыта
local closedCF = door.CFrame
-- время прошлой попытки каждого игрока
local last = {}
-- открыта?
local open = false

-- открыть и через время закрыть
local function Open()
    -- уже открыта
    if open then return end
    -- открыта
    open = true
    -- уезжает вверх
    TS:Create(door, TweenInfo.new(1), {CFrame = closedCF + Vector3.new(0, door.Size.Y, 0)}):Play()
    -- стоит открытой
    task.wait(config.OpenTime.Value)
    -- закрывается
    TS:Create(door, TweenInfo.new(1), {CFrame = closedCF}):Play()
    -- доехала
    task.wait(1)
    -- закрыта
    open = false
-- конец функции
end

-- игрок нажал OK
tryCode.OnServerInvoke = function(player, code)
    -- прислали не текст
    if typeof(code) ~= "string" then return false end
    -- не чаще двух попыток в секунду — перебором не взломать
    if os.clock() - (last[player] or 0) < 0.5 then return false end
    -- запоминаем
    last[player] = os.clock()
    -- где игрок
    local root = player.Character and player.Character:FindFirstChild("HumanoidRootPart")
    -- издалека не открыть
    if not root or (root.Position - door.Position).Magnitude > 20 then return false end
    -- неверно
    if code ~= CODE then return false end
    -- открываем, не задерживая ответ
    task.spawn(Open)
    -- верно
    return true
-- конец функции
end

KeypadLocal

Где: StarterPlayer → StarterPlayerScripts · LocalScript
Зачем: Окно с кнопками и отправка кода.

-- все надписи ProximityPrompt
local PPS = game:GetService("ProximityPromptService")
-- этот игрок
local player = game.Players.LocalPlayer
-- окно кодового замка
local gui = player:WaitForChild("PlayerGui"):WaitForChild("KeypadGui")
-- окно
local frame = gui:WaitForChild("Frame")
-- экранчик
local display = frame:WaitForChild("Display")
-- место для кнопок
local grid = frame:WaitForChild("Grid")
-- крестик
local closeButton = frame:WaitForChild("Close")
-- не больше 6 цифр
local MAX = 6
-- дверь, у которой стоим
local current = nil
-- набранный код
local code = ""

-- написать на экранчике
local function Show(text, color)
    -- текст
    display.Text = text
    -- цвет
    display.TextColor3 = color or Color3.new(1, 1, 1)
-- конец функции
end

-- нажата кнопка
local function Press(key)
    -- окно не открыто
    if not current then return end
    -- стереть
    if key == "C" then
        -- код пустой
        code = ""
        -- экран пустой
        Show("")
    -- проверить
    elseif key == "OK" then
        -- сервер сравнит с настоящим кодом
        local ok = current.TryCode:InvokeServer(code)
        -- набор сбрасываем
        code = ""
        -- верно
        if ok then
            -- зелёным
            Show("ОТКРЫТО", Color3.fromRGB(90, 230, 120))
            -- пусть прочитает
            task.wait(0.8)
            -- закрываем окно
            frame.Visible = false
            -- дверь забыли
            current = nil
        -- неверно
        else
            -- красным
            Show("НЕВЕРНО", Color3.fromRGB(240, 80, 80))
        -- конец проверки
        end
    -- цифра, и место ещё есть
    elseif #code < MAX then
        -- добавляем цифру
        code ..= key
        -- показываем точками
        Show(string.rep("•", #code))
    -- конец выбора
    end
-- конец функции
end

-- 12 кнопок: скрипт создаёт их сам
for i, key in ipairs({"1", "2", "3", "4", "5", "6", "7", "8", "9", "C", "0", "OK"}) do
    -- кнопка
    local button = Instance.new("TextButton")
    -- имя
    button.Name = key
    -- надпись
    button.Text = key
    -- порядок в сетке
    button.LayoutOrder = i
    -- текст по размеру
    button.TextScaled = true
    -- жирный
    button.Font = Enum.Font.GothamBold
    -- белый
    button.TextColor3 = Color3.new(1, 1, 1)
    -- OK зелёная, C красная
    button.BackgroundColor3 = key == "OK" and Color3.fromRGB(70, 170, 90) or key == "C" and Color3.fromRGB(190, 70, 70) or Color3.fromRGB(60, 60, 75)
    -- в сетку
    button.Parent = grid
    -- нажатие
    button.MouseButton1Click:Connect(function() Press(key) end)
-- конец перебора
end

-- крестик
closeButton.MouseButton1Click:Connect(function()
    -- закрываем
    frame.Visible = false
    -- дверь забыли
    current = nil
-- конец обработчика
end)

-- игрок нажал E у какой-то надписи
PPS.PromptTriggered:Connect(function(prompt)
    -- модель, в которой надпись
    local model = prompt.Parent and prompt.Parent.Parent
    -- это не кодовый замок
    if prompt.Parent.Name ~= "Keypad" or not model:FindFirstChild("TryCode") then return end
    -- запоминаем дверь
    current = model
    -- набор с нуля
    code = ""
    -- экран пустой
    Show("")
    -- открываем окно
    frame.Visible = true
-- конец обработчика
end)

Проверка

Запусти Play (или Run) и убедись:

Собрать дверь с кодом одной командой