# Lua API Рублокса (справочник для скриптеров)

Этот документ — полный список того, что работает в Lua-скриптах Рублокса.
API максимально приближен к Roblox, чтобы можно было переносить чужие
скрипты с минимальными правками.

> **Как переключить скрипт на Lua:** в шапке вкладки редактора кода кликни
> по переключателю **JS / Lua**. Подсветка синтаксиса и автодополнение
> автоматически переключатся.

---

## Содержание

1. [Базовые типы](#базовые-типы)
2. [DataModel: game, workspace, Players](#datamodel)
3. [Part — куб на сцене](#part)
4. [Создание и удаление](#создание-и-удаление)
5. [События: Touched, Heartbeat, RemoteEvent](#события)
6. [Таймеры: task.wait, task.delay](#таймеры)
7. [GUI: TextLabel, TextButton, Frame](#gui)
8. [Звук: Sound](#звук)
9. [Анимации: TweenService](#tweenservice)
10. [Игрок: Humanoid, LocalPlayer](#игрок)
11. [Чего пока нет](#чего-пока-нет)

---

## Базовые типы

### `Vector3`

```lua
local v = Vector3.new(1, 2, 3)
print(v.X, v.Y, v.Z)             -- 1 2 3
print(v.Magnitude)                -- 3.7416...  (длина)
print(v.Unit)                     -- нормализованный
print(v:Dot(otherVec))            -- скалярное произведение
print(v:Cross(otherVec))          -- векторное произведение
local mid = v:Lerp(otherVec, 0.5) -- линейная интерполяция

-- Константы:
Vector3.zero   -- (0,0,0)
Vector3.one    -- (1,1,1)
Vector3.xAxis  -- (1,0,0)
Vector3.yAxis, Vector3.zAxis
```

Поддержаны операторы: `+`, `-`, `*` (на число), `/`, унарный `-`.

### `Color3`

```lua
local c = Color3.new(0.5, 0.2, 0.8)        -- 0..1 каждый
local c2 = Color3.fromRGB(255, 128, 0)     -- 0..255
local c3 = Color3.fromHSV(0.1, 0.8, 1)
local c4 = Color3.fromHex("#FF8000")
local mid = c:Lerp(c2, 0.5)
print(c:ToHex())  -- "#7F33CC"
```

### `UDim2` / `UDim` / `Vector2`

Для GUI-координат:

```lua
local pos = UDim2.new(0.5, 0, 0.5, 0)   -- центр экрана (scale/offset)
local pos2 = UDim2.fromScale(0.2, 0.1)
local pos3 = UDim2.fromOffset(100, 50)  -- в пикселях
```

### `CFrame`

```lua
local cf = CFrame.new(0, 10, 0)         -- позиция
local cf2 = CFrame.lookAt(eye, target)  -- упрощённый
print(cf.Position)                       -- Vector3
```

### `Enum`

```lua
Enum.KeyCode.W
Enum.KeyCode.Space
Enum.Material.Plastic, Enum.Material.Neon, Enum.Material.Wood
Enum.UserInputType.MouseButton1
Enum.HumanoidStateType.Running
```

---

## DataModel

Виртуальное дерево, как в Roblox:

```lua
game                       -- корневой DataModel
game.Workspace             -- = workspace (короче)
game.Players               -- сервис игроков
game.Players.LocalPlayer   -- локальный игрок
game.ReplicatedStorage     -- хранилище общих ресурсов
game.StarterGui            -- стартовое GUI
game.Lighting              -- свет
```

Методы:

```lua
local svc = game:GetService("RunService")
local part = workspace:FindFirstChild("Coin")
local part2 = workspace:FindFirstChildOfClass("Part")
local all = workspace:GetChildren()       -- массив всех детей
local descendants = workspace:GetDescendants()
local sib = workspace.Coin:FindFirstAncestorOfClass("Workspace")
print(workspace:IsA("Workspace"))         -- true
```

---

## Part

`Part` — куб/сфера/цилиндр на сцене. **Это обёртка над примитивом Рублокса.**
Скрипт привязанный к кубу получает его через `script.Parent`:

```lua
-- script.Parent — Part к которому прицеплен скрипт
print(script.Parent.Name)              -- "Part_1"

-- Чтение свойств
print(script.Parent.Position)          -- Vector3
print(script.Parent.Size)              -- Vector3
print(script.Parent.Color)             -- Color3
print(script.Parent.Anchored)          -- bool
print(script.Parent.CanCollide)        -- bool
print(script.Parent.Transparency)      -- 0..1

-- Запись (двигает куб в реальном времени!)
script.Parent.Position = Vector3.new(0, 10, 0)
script.Parent.Size = Vector3.new(5, 1, 5)
script.Parent.Color = Color3.fromRGB(255, 0, 0)
script.Parent.Anchored = false           -- куб начнёт падать (физика)
script.Parent.Transparency = 0.5         -- полупрозрачный
script.Parent.CFrame = CFrame.new(0, 20, 0)
```

---

## Создание и удаление

### `Instance.new`

```lua
-- Создать Part на сцене
local p = Instance.new("Part")
p.Position = Vector3.new(0, 5, 0)
p.Size = Vector3.new(2, 2, 2)
p.Color = Color3.fromRGB(255, 100, 0)
p.Anchored = true
p.Parent = workspace

-- Удалить через 3 секунды
task.delay(3, function()
    p:Destroy()
end)
```

Поддержанные классы:
- **Сцена:** `Part`, `WedgePart`, `MeshPart`
- **События:** `RemoteEvent`, `BindableEvent`
- **GUI:** `ScreenGui`, `Frame`, `TextLabel`, `TextButton`, `ImageLabel`,
  `ImageButton`, `TextBox`, `ScrollingFrame`
- **Звук:** `Sound`
- **Прочее:** `Folder`, `Humanoid`, `Configuration`, любой `ClassName`

---

## События

### `script.Parent.Touched` — касание игрока

```lua
script.Parent.Touched:Connect(function(hit)
    print("Игрок коснулся!", hit.Name)
    local h = game.Players.LocalPlayer.Character:FindFirstChildOfClass("Humanoid")
    if h then
        h:TakeDamage(100)  -- KillBrick
    end
end)
```

### `RunService.Heartbeat` — каждый кадр

```lua
local RunService = game:GetService("RunService")
RunService.Heartbeat:Connect(function(dt)
    -- dt — время с прошлого кадра (~0.016)
    script.Parent.Position = script.Parent.Position + Vector3.new(0, 0.1, 0)
end)
```

### `BindableEvent` / `RemoteEvent` — общение между скриптами

```lua
-- Скрипт A создаёт событие в общем месте
local event = Instance.new("BindableEvent")
event.Name = "MyEvent"
event.Parent = game.ReplicatedStorage

-- Скрипт B подписывается
local event = game.ReplicatedStorage:WaitForChild("MyEvent")
event.Event:Connect(function(msg, num)
    print("Получено:", msg, num)
end)

-- Скрипт A триггерит
event:Fire("привет", 42)
```

### `Humanoid.Died`

```lua
local h = game.Players.LocalPlayer.Character:FindFirstChildOfClass("Humanoid")
h.Died:Connect(function()
    print("игрок умер")
end)
h.HealthChanged:Connect(function(newHp)
    print("здоровье:", newHp)
end)
```

---

## Таймеры

### `task.wait(сек)` — приостановить скрипт

```lua
print("сейчас")
task.wait(1)
print("через секунду")
```

`task.wait` **не блокирует** другие скрипты — это yield через coroutines.
Можно использовать в `while true do ... task.wait(0.1) end` без проблем.

### `task.delay(сек, fn)` — выполнить через

```lua
task.delay(2, function()
    print("через 2 секунды")
end)
```

### `task.spawn(fn)` — асинхронно

```lua
task.spawn(function()
    print("параллельно с основным потоком")
end)
```

---

## GUI

### Базовая иерархия

```lua
-- ScreenGui — корень всех GUI
local sg = Instance.new("ScreenGui")
sg.Parent = game.Players.LocalPlayer.PlayerGui

-- TextLabel — статичный текст
local label = Instance.new("TextLabel")
label.Parent = sg
label.Text = "Привет!"
label.TextColor3 = Color3.fromRGB(255, 255, 0)
label.BackgroundColor3 = Color3.fromRGB(50, 30, 20)
label.Position = UDim2.new(0.4, 0, 0.1, 0)   -- 40% от ширины, 10% от высоты
label.Size = UDim2.new(0.2, 0, 0.05, 0)
label.TextSize = 24

-- TextButton — кликабельная кнопка
local btn = Instance.new("TextButton")
btn.Parent = sg
btn.Text = "Нажми"
btn.Position = UDim2.new(0.4, 0, 0.5, 0)
btn.Size = UDim2.new(0.2, 0, 0.08, 0)
btn.MouseButton1Click:Connect(function()
    print("Клик!")
    label.Text = "Нажата!"
end)
```

### Свойства

| Свойство             | Тип       | Описание                          |
|----------------------|-----------|-----------------------------------|
| `Text`               | string    | Видимый текст                     |
| `TextColor3`         | Color3    | Цвет текста                       |
| `TextSize`           | number    | Размер шрифта                     |
| `BackgroundColor3`   | Color3    | Цвет фона                         |
| `BackgroundTransparency` | 0..1  | 0=сплошной, 1=прозрачный          |
| `Position`           | UDim2     | Позиция (scale=%, offset=px/10)   |
| `Size`               | UDim2     | Размер                            |
| `Visible`            | bool      | Виден или нет                     |

### События кнопок

```lua
btn.MouseButton1Click:Connect(fn)  -- ЛКМ клик
btn.MouseEnter:Connect(fn)         -- наведение
btn.MouseLeave:Connect(fn)         -- увод
btn.Activated:Connect(fn)          -- = MouseButton1Click
```

---

## Звук

```lua
local sound = Instance.new("Sound")
sound.SoundId = "coin"       -- или "jump", "win", "lose", "hit", "click", "pickup"
sound.Volume = 1             -- 0..2
sound.PlaybackSpeed = 1      -- pitch
sound:Play()
```

Также Roblox-AssetID работает с эвристикой:

```lua
sound.SoundId = "rbxassetid://1234567890"  -- автоподбор по имени переменной
```

Поддержанные звуки (процедурные, не из файлов):
- `jump` — прыжок
- `pickup` — подбор
- `coin` — звон монеты
- `win` — победа
- `lose` — поражение
- `click` — клик
- `hit` — удар

Зацикливание:

```lua
sound.Looped = true
sound:Play()  -- играет до sound:Stop()
```

---

## TweenService

Плавная анимация свойств:

```lua
local TweenService = game:GetService("TweenService")

local part = script.Parent
local tween = TweenService:Create(
    part,
    { Time = 2 },                              -- длительность 2 сек
    { Position = Vector3.new(0, 20, 0),
      Color = Color3.fromRGB(255, 0, 0) }      -- цели
)
tween:Play()

tween.Completed:Connect(function()
    print("Анимация завершилась!")
end)
```

Работает с `Position`, `Size`, `Color` (Vector3/Color3) и числовыми
свойствами (`Transparency`, `TextSize`, и т.д.).

---

## Игрок

### `game.Players.LocalPlayer`

```lua
local plr = game.Players.LocalPlayer
print(plr.Name, plr.UserId, plr.DisplayName)
print(plr.Character)                              -- Model
```

### `Humanoid`

```lua
local char = game.Players.LocalPlayer.Character
local h = char:FindFirstChildOfClass("Humanoid")

print(h.Health, h.MaxHealth)
print(h.WalkSpeed)        -- скорость ходьбы
print(h.JumpPower)        -- сила прыжка

h.Health = 0              -- мгновенная смерть → респавн
h:TakeDamage(50)          -- урон с учётом invulnerability

h.Died:Connect(function()
    print("Помер")
end)
h.HealthChanged:Connect(function(newHp)
    if newHp < 30 then
        print("Здоровье низкое!")
    end
end)
```

### `HumanoidRootPart`

```lua
local hrp = char:FindFirstChild("HumanoidRootPart")
print(hrp.Position)
```

---

## Чего пока нет

Не работает (пока):

- **Скрипты не делятся на Server/LocalScript** — все скрипты client-side.
- **DataStoreService** — методы есть, но возвращают nil/no-op.
- **`workspace:Raycast`** / **`game.Lighting.ClockTime`** — заглушки.
- **`Players.PlayerAdded`** — никогда не фейерится (только один игрок).
- **3D-анимации (`Animation` instance + `AnimationController`)** —
  `LoadAnimation` возвращает заглушку.
- **`Sound` из файлов** — только встроенные процедурные.
- **`SurfaceGui` / `BillboardGui`** — нет, только `ScreenGui`.
- **`Model:MoveTo` / `:SetPrimaryPartCFrame`** — нет.
- **Networking (`RemoteFunction:InvokeServer`)** — RemoteEvent работает
  только в пределах одного клиента.

Если что-то из этого критично — открой issue в репо.

---

## Пример: KillBrick + монета + GUI-счётчик

Положи 1 куб и 1 шарик на сцене. К каждому привяжи скрипт:

**На кубе (KillBrick):**
```lua
script.Parent.Color = Color3.fromRGB(200, 30, 30)
script.Parent.Touched:Connect(function()
    local h = game.Players.LocalPlayer.Character:FindFirstChildOfClass("Humanoid")
    if h then h:TakeDamage(100) end
end)
```

**На шарике (Coin):**
```lua
script.Parent.Color = Color3.fromRGB(255, 215, 0)
script.Parent.Touched:Connect(function()
    -- Запускаем событие на ReplicatedStorage
    local re = game.ReplicatedStorage:FindFirstChild("CoinPicked")
    if not re then
        re = Instance.new("BindableEvent")
        re.Name = "CoinPicked"
        re.Parent = game.ReplicatedStorage
    end
    re:Fire()
    script.Parent:Destroy()
end)
```

**Глобальный скрипт (GUI):**
```lua
local sg = Instance.new("ScreenGui")
sg.Parent = game.Players.LocalPlayer.PlayerGui

local label = Instance.new("TextLabel")
label.Parent = sg
label.Text = "Монет: 0"
label.Position = UDim2.new(0.05, 0, 0.05, 0)
label.Size = UDim2.new(0.1, 0, 0.05, 0)
label.TextSize = 20
label.TextColor3 = Color3.fromRGB(255, 215, 0)

local count = 0
task.spawn(function()
    while not game.ReplicatedStorage:FindFirstChild("CoinPicked") do
        task.wait(0.1)
    end
    game.ReplicatedStorage.CoinPicked.Event:Connect(function()
        count = count + 1
        label.Text = "Монет: " .. count
        local sound = Instance.new("Sound")
        sound.SoundId = "coin"
        sound:Play()
    end)
end)
```

Получится: красный куб убивает, золотая монета даёт +1 к счётчику со
звуком.

---

**Версия документации:** Этап 7 (готово после реализации Этапов 1-6).
Если что-то описанное здесь не работает — это баг, репортуй.
