8a66ce03f9
Merge remote-tracking branch 'origin/main' into feat/lua-50-games-bundle
CI / Lint (pull_request) Failing after 1m11s
CI / Build (pull_request) Successful in 1m57s
CI / Secret scan (pull_request) Successful in 23s
CI / PR size check (pull_request) Successful in 7s
CI / Deploy to S1 + S2 (pull_request) Has been skipped
2026-06-10 00:20:52 +03:00
09a927bbfc
fix(docs): дефолт языка в статьях — JS, не Lua
...
Дефолт в DEFAULT_LANG уже был 'js', но у части юзеров в localStorage
залип 'lua' с прошлого посещения (rublox.docs.lang).
Фикс: бамп ключа на 'rublox.docs.lang.v2' + удаление старого ключа
при инициализации. У всех теперь старт с JS, переключение на Lua
сохраняется по новому ключу как раньше.
2026-06-09 23:43:12 +03:00
eedac4379d
feat: импорт Roblox открыт для всех + раздел вики
...
KubikonStudio.jsx: убрана проверка getCurrentUserId()===1 на кнопке
'📦 Импорт Roblox'. Теперь доступно всем юзерам.
RbxlImportModal.jsx: убран гейт ALLOWED_USER_ID и заглушка
'доступна только администратору'.
API.js: убран комментарий 'только для МИНа' у RBXL_addres.
docsData.jsx: новый раздел вики 'rbxl-import' (icon: package,
title: 'Импорт из Roblox') с 5 статьями:
- I1. Что это и зачем
- I2. Как импортировать карту (шаги 1-4)
- I3. Графика хорошо, скрипты — осторожно
(что переносится хорошо/так себе/не переносится)
- I4. Правильный порядок: сначала графика, потом скрипты
(Проход 1: импорт со скриптами 'Отключены' → смотрим графику,
Проход 2: включаем скрипты по одному в редакторе)
- I5. Советы и частые проблемы
(пустая карта, серые текстуры, тормоза, DataStoreService,
провал под пол + что делать после импорта)
Раздел вставлен перед 'collab' (Совместное редактирование).
2026-06-09 23:39:08 +03:00
61026a1df0
feat(docs): компонент <Api> переключает JS/Lua инлайны
...
В уроке 50 (и можно дальше) в тексте было много <code>game.ui.showText</code>,
<code>game.broadcast</code> и т.д. — это JS-API. В Lua-вкладке вики они
оставались JS — путало юзера.
Фикс:
- Новый компонент <Api js="..." lua="..." /> использует useDocsLang().
Если lang='lua' и lua задан — показывает Lua-эквивалент.
- В уроке 50 заменил все инлайны game.* на <Api> с Lua-параллелями:
- game.ui.showText → __rbxl_show_text
- game.sound.play → winSound:Play()
- game.onMessage/broadcast → BindableEvent:Connect/Fire
- game.self.onTouch/onInteract/onClick → Touched/UIS+Heartbeat/ClickDetector
- game.onTick → RunService.Heartbeat
- game.after/every → task.delay/spawn
- game.tween → TweenService:Create
- game.scene.spawnNpc → __rbxl_spawn_npc
- game.ui.score → __rbxl_score_set
2026-06-09 23:29:41 +03:00
ddeb8ff93f
docs(49) + feat(g50): «Своя игра» (песочница)
...
g49 docs: CodeBoth main+finish.
g50 паритет:
- Комментарии-инструкция как начать свою игру (5 шагов)
- __rbxl_show_text 'Твоя песочница! Создай свою игру'
2026-06-09 23:21:39 +03:00
3a95cd148a
docs(48) + feat(g49): «Мультиплеер: Гонка»
...
g48 docs: CodeBoth g48_main.
g49 паритет (упрощённый без MP-API):
- showText 'Гонка! Беги к финишу первым'
- hud_set 'info' 'Игроков: N | Победил: X' (Players:GetPlayers count + LocalPlayer name)
- Players.PlayerAdded/Removing → refresh
- BindableEvent FinishReached
- g49_finish: Touched → FinishReached:Fire (fired-флаг)
- При победе: winnerName = LocalPlayer.Name + refresh + 'Победа!' + confetti
2026-06-09 23:18:39 +03:00
e78f585fd4
docs(47) + feat(g48): «Мультиплеер: Салки»
...
g47 docs: CodeBoth main+btn_1+finish.
g48 паритет (упрощённый — без MP-API):
- __rbxl_show_text 'Опубликуй игру для игры с друзьями'
- __rbxl_hud_set 'info' 50,8 'Игроков в комнате: N' (Players:GetPlayers)
- Players.PlayerAdded → '<имя> присоединился!' + refresh
- Players.PlayerRemoving → refresh
- task.delay 2 показывает правила
- В одиночке роли не назначаются (нет game.room API в shim)
2026-06-09 23:15:11 +03:00
57c5779644
docs(46) + feat(g47): «Квест-побег»
...
g46 docs: CodeBoth 4 скрипта (main+cube+up1+up2).
g47 паритет:
- TOTAL=3, pressed/escaped counters
- BindableEvents ButtonPressed/Escape
- 3 g47_btn_N: Heartbeat distance(3) + '[E] Нажать кнопку'
E → used=true + Color зелёный + ButtonPressed:Fire
- При pressed>=3: tween двери Position.Y+6 + CanCollide=false + win sound
- g47_finish: Touched → Escape:Fire → 'Победа! Сбежал!' + confetti
2026-06-09 23:12:28 +03:00
d758fdfbe6
docs(45) + feat(g46): «Кликер»
...
g45 docs: CodeBoth g45_main.
g46 паритет (заменил simpleClicker fallback):
- GOAL=200, points/perClick/autoIncome
- Heartbeat: каждую секунду points += autoIncome → checkWin
- BindableEvents CubeClicked/BuyPower/BuyAuto
- g46_cube: ClickDetector → CubeClicked:Fire + sparks
- g46_up1/up2: Heartbeat distance(3) + '[E] Купить ...' + InputBegan E
- buyPower: -20 + perClick+=2
- buyAuto: -40 + autoIncome+=3
2026-06-09 23:07:25 +03:00
1c5e5fe5bb
docs(44) + feat(g45): «Стрелялка-арена»
...
g44 docs: CodeBoth main+slot_1.
g45 паритет:
- GOAL=15, score/over
- Humanoid.Died → 'Поражение!'
- BindableEvent EnemyClicked(ref)
- Heartbeat spawn 1.8с: радиус=11 cos/sin → npc 'character-b'
hp=30 speed=2.2 follow('player')
- npc_on_click → EnemyClicked:Fire(ref)
- Главный: dist<6 → npc.remove + explosion + score++
- 15 → 'Победа!' + confetti
- Heartbeat damage: каждый враг dist<1.8 + last>0.7 → damage_player(10) + hit
2026-06-09 23:04:21 +03:00
dc669a51f4
docs(43) + feat(g44): «Tower Defense»
...
g43 docs: CodeBoth main+boost_1+spike_4+finish.
g44 паритет:
- GOAL=14, MAX_LEAK=8, killed/leaked counters
- towers[] и enemies{} (ref-keyed)
- BindableEvent TowerBuilt(x, z)
- Heartbeat spawn: 2.2с → npc 'character-b' speed=2 hp=50 в (-0.5,1,-3),
task.delay 0.3 moveTo (-0.5, 42), on_death → killed++
- Heartbeat fire: 0.8с → каждая башня бьёт ближайшего врага в r=7
(npc.damage 25 + sparks)
- Heartbeat leak: 0.5с → ez>40 → npc.remove + leaked++ + lose
- 4 g44_slot_N: Heartbeat distance(4) + '[E] Построить башню'
E → Instance.new('Part') Cylinder жёлтый + TowerBuilt:Fire
2026-06-09 23:00:37 +03:00
019068cffa
docs(42) + feat(g43): «Гонка с препятствиями»
...
g42 docs: CodeBoth 4 скрипта.
g43 паритет:
- Heartbeat: time += dt → timer
- BindableEvents Boost/Spike/FinishReached
- Boost → set_speed(1.8) + pickup + 'УСКОРЕНИЕ!', task.delay 3 → set_speed(1)
- Spike → damage_player(15) + set_speed(0.5) + hit, task.delay 1.5 → 1
- Finish → 'Финиш! Время: X сек' + confetti
- 3 g43_boost_N + 5 g43_spike_N: Touched throttle 1с → Fire соответствующее
- g43_finish: Touched → FinishReached:Fire
Shim: __rbxl_set_speed(mul) → cmd 'player.setSpeed' с полем 'mul'.
2026-06-09 22:55:54 +03:00
4085fce0d3
docs(41) + feat(g42): «RPG-деревня»
...
g41 docs: CodeBoth 4 скрипта (main+coin_10+cp+finish).
g42 паритет:
- 2 NPC (Староста character-a, Кузнец character-b)
- stage 0→1→2→3 цепочка
- BindableEvents ElderTalk/TakeAmulet/SmithTalk
- g42_elder/smith: Heartbeat distance(4) + '[E] Поговорить'
InputBegan E → Fire
- g42_amulet: Touched → TakeAmulet:Fire + Destroy
- stage 1 elder: 'Найди амулет'
- stage 1 amulet: __rbxl_inventory_define/add 'amulet'
- stage 2 smith: inventory_remove + 'Победа!' + confetti
- Прочие говорят соответствующую реплику
2026-06-09 22:52:22 +03:00
e75121cb3d
docs(40) + feat(g41): «Платформер-приключение»
...
g40 docs: CodeBoth g40_main.
g41 паритет:
- Heartbeat py<-3 → LoadCharacter + lose
- BindableEvents CoinCollected/CheckpointReached/TreasureFound
- 5 g41_coin_N (id 10..14): Touched → CoinCollected:Fire + Destroy
- g41_cp: Touched → CheckpointReached:Fire → setSpawn(-0.5,7,28)
- g41_finish: Touched → TreasureFound:Fire → 'Победа! Сокровище и N монет!' + confetti
2026-06-09 22:49:14 +03:00
cce9d2e293
docs(39) + feat(g40): «Выживание от волн»
...
g39 docs: CodeBoth main+spot_1.
g40 паритет:
- WAVES=3, count=wave+2 (3,4,5 врагов)
- Враги по кругу radius=10 (cos/sin), npc.follow('player')
- BindableEvent EnemyClicked(ref)
- __rbxl_npc_on_click(ref, fn) — каждый враг шлёт ref в общий event
- Главный проверяет dist<5, npc.remove + explosion + aliveInWave--
- 0 живых → task.delay 2 startWave (forward-decl)
- 3 волны → 'Победа!' + confetti
2026-06-09 22:46:21 +03:00
f7b296f43b
fix(g39): 3D-дистанция для distance-check мест
...
8 мест-призраков стоят один над другим (x=0, z=0, y=1,3,5,...).
По X+Z они в (0,0) → все 8 видят hintVisible=true одновременно
→ нажатие E срабатывало у всех сразу, башня строилась за раз.
Фикс: 3D-дистанция (учитываем dy).
2026-06-09 22:43:40 +03:00
b42685521c
docs(38) + feat(g39): «Башня — стройка»
...
g38 docs: CodeBoth main+tile_1.
g39 паритет:
- STEPS=8, placed counter
- BindableEvent BlockPlaced(n)
- 8 g39_spot_N: Heartbeat distance(4) → '[E] Поставить блок'
E → CanCollide=true, Transparency=0, Color коричневый,
BlockPlaced:Fire(n)
- Главный: n=placed+1? placed++; иначе 'Сначала поставь ниже!'
- 8 → 'Победа!' + confetti
2026-06-09 22:41:55 +03:00
0fcc5b85d0
docs(37) + feat(g38): «Музыкальная игра»
...
g37 docs: CodeBoth main+spike_1+cp+finish.
g38 паритет:
- SOUNDS [coin,jump,click,hit], SEQ [1,3,2,4,1]
- task.delay 1 + i*0.8 → play sound + 'Нота N из 5'
- После последней task.delay → canPress=true + 'Повтори!'
- BindableEvent NotePressed(n)
- 4 g38_tile_N: Heartbeat distance(3) → '[E] Сыграть ноту'
E → tileSound + sparks + NotePressed:Fire(n)
- Правильная → playerStep++, при #SEQ → win + confetti
- Ошибка → playerStep=0 + lose + 'Слушай снова'
2026-06-09 22:35:40 +03:00
f0025f0dad
docs(36) + feat(g37): «Полоса препятствий»
...
g36 docs: CodeBoth main+box_1.
g37 паритет:
- task.delay 0.2 ДвижПлатформа yoyo loop (x: -0.5 ↔ 3, 2с)
- Heartbeat: py<-3 → LoadCharacter + lose
- BindableEvents CheckpointReached/FinishReached
- 6 g37_spike_N: Touched → damage(25) + hit sound (i-frames 0.5с)
- g37_cp: Touched → CheckpointReached:Fire → setSpawn(-0.5,1,24)
- g37_finish: Touched → FinishReached:Fire → win + confetti
Shim: __rbxl_set_spawn(x,y,z).
2026-06-09 22:32:55 +03:00
b0bdfb6e29
docs(35) + feat(g36): «Головоломка с ящиками»
...
g35 docs: CodeBoth g35_main.
g36 паритет:
- onPlate[3] флаги, при всех true → win
- BindableEvent BoxMoved(i, on)
- g36_box_N: Heartbeat distance-check(3) → '[E] Двинуть ящик',
E: cell++ (wrap), TweenService Position.Z=ROW[cell], 0.4с,
Fire(i, newZ == 6)
2026-06-09 22:29:36 +03:00
92a9ef220d
docs(34) + feat(g35): «Прятки от NPC»
...
g34 docs: CodeBoth main+plant_1.
g35 паритет:
- SURVIVE=40c, NPC 'Искатель' speed=3 follow('player')
- __rbxl_timer_set каждый кадр
- dist<1.7 → LoadCharacter + 'Найден!' + lose (с throttle 2с)
- time>=40 → npc.stop + 'Победа!' + confetti + win
2026-06-09 22:25:20 +03:00
3e572e1136
docs(33) + feat(g34): «Сбор урожая»
...
g33 docs: CodeBoth g33_main.
g34 паритет:
- BindableEvent Harvested → score++ + coin sound, 6 → win + confetti
- 6 g34_plant_N: TweenService 5с растёт (Size+Position),
Completed → ripe=true + Color жёлтый
- Heartbeat distance-check (3) → __rbxl_hud_set '[E] Собрать'
- E: не ripe → 'Ещё не выросло!'; ripe → Harvested:Fire + Destroy
2026-06-09 22:22:03 +03:00
f3b0cabdbd
docs(32) + feat(g33): «Платформер с боссом»
...
g32 docs: CodeBoth main+cp_1.
g33 паритет:
- Heartbeat: py<-3 → LoadCharacter + lose
- При pz>24 + py>5 (на арене) — spawnNpc 'БОСС' hp=120 speed=2
- task.delay npc.follow('player') + setLabel 'БОСС HP: 120'
- __rbxl_npc_on_click(bossRef, onBossHit):
dist<5 → bossHp -= 20 + npc.damage + setLabel + sparks + hit
- __rbxl_npc_on_death → clear_label + 'Победа!' + confetti + win
2026-06-09 22:18:18 +03:00
4ca3800e49
docs(31) + feat(g32): «Гонка с кругами»
...
g31 docs: CodeBoth для g31_main.
g32 паритет:
- LAPS=2, CP_COUNT=4, nextCp/lap/time/won
- __rbxl_timer_set — паритет с game.ui.timer=N (формат mm:ss)
- __rbxl_hud_set 'race' — постоянная надпись 'Круг N/2 • чекпоинт M/4'
- Heartbeat: time += dt → timer update
- BindableEvent CheckpointReached(num)
- 4 g32_cp_N: Touched → CheckpointReached:Fire(N)
- При 2 кругах → 'ФИНИШ! Xc' + showText + confetti + win
Shim: __rbxl_timer_set(seconds).
2026-06-09 22:15:16 +03:00
901c249c29
docs(29) + feat(g31): «Защита базы»
...
g30 docs CodeBoth 4 скрипта.
g31:
- killed counter (GOAL=12) + leaked (MAX_LEAK=5)
- Heartbeat spawn враг каждые 2с в (random(-8,8), 1, 38),
spawn 'character-b' speed 2.5
- task.delay 0.3 npc.moveTo(0, 2) — к базе
- __rbxl_npc_on_click(ref, fn) → шлёт ref в общий BindableEvent
- При клике главный скрипт проверяет dist<5, наносит урон
- Каждые 0.4с проверка прорыва (z<4) → leaked++ + lose sound
- 12 убитых → 'Победа!' + confetti
- 5 прорывов → 'База разрушена!'
Shim: __rbxl_npc_moveto/__rbxl_npc_remove.
2026-06-09 22:11:15 +03:00
f69df55e3b
docs: CodeBoth урока 29 + feat(g30): полный паритет «Квест с заданиями»
...
g29 docs: 5 скриптов под CodeBoth (main, coin_1, shop, door, finish).
g30 паритет:
- stage 0→1→2→3→4 (talk/coin/flag/talk)
- setObjective через __rbxl_hud_set 50,8 цвет/размер
- NPC 'Старейшина' spawnNpc + npc_say на этапах
- BindableEvents Talk/CoinDone/FlagDone
- g30_npc: Heartbeat distance-check (4) + '[E] Поговорить' + InputBegan E
- g30_coin: Touched → CoinDone:Fire + Destroy (taken-флаг)
- g30_flag: Touched → FlagDone:Fire (fired-флаг)
- На stage 3: showText + confetti + win sound
2026-06-09 22:06:27 +03:00
5186ee3b70
feat(g29): добавлен NPC-продавец за прилавком с меткой 'Продавец'
2026-06-09 22:03:06 +03:00
facd6aa837
feat(g29): полный паритет «Магазин»
...
JS:
- 7 монеток onTouch → broadcast coin → score++, coin sound
- прилавок onInteract E (4) → broadcast buy → coins>=5? покупка ключа
+ inventory.add('Ключ') + 'Куплен!' + win sound; иначе lose+'Мало!'
- дверь onInteract E (4) → broadcast open-door → hasKey? tween y+6;
иначе 'Дверь заперта'
- финиш → broadcast win → 'Победа!' + confetti
Lua (паритет):
- BindableEvents CoinCollected/BuyKey/OpenDoor/WinReached
- __rbxl_score_set, __rbxl_show_text, __rbxl_inventory_define/add
- 7 g29_coin_N: Touched → CoinCollected:Fire + Destroy
- g29_shop, g29_door: Heartbeat distance-check (4) + __rbxl_hud_set
'[E] Купить ключ (5 монет)' / '[E] Открыть дверь' + InputBegan E
- g29_main обрабатывает все события, при покупке: TweenService двери
Position.Y+6 + CanCollide=false
- g29_finish: Touched → WinReached:Fire (fired-флаг)
2026-06-09 22:00:35 +03:00
ed23ec782c
docs: CodeBoth для урока 28 «Призрачные стены» (main+wall+finish)
2026-06-09 21:58:44 +03:00
a72101a29a
fix(g28): ClickDetector вместо part.Clicked (как в Тире)
...
part.Clicked не существует — был fallback try/catch с молчаливым
падением. ClickDetector + MouseClick — рабочий путь (используется
в игре 15 «Тир»).
2026-06-09 21:57:38 +03:00
095a79cab4
feat(g28): полный паритет «Призрачные стены»
...
JS:
- showText 'Кликай по фиолетовым стенам — пройди сквозь!'
- onMessage 'win' → 'Победа!' + win + confetti
- 4 стены: onClick → passThrough + opacity=0.25 + click sound + showText
- финиш: onTouch → broadcast 'win'
Lua (паритет):
- __rbxl_show_text + Sounds
- BindableEvent WinReached
- 4 g28_wall_N: part.Clicked → CanCollide=false + Transparency=0.75 +
click Sound + showText 'Стена стала призрачной!'
- g28_finish: Touched → WinReached:Fire (fired-флаг)
2026-06-09 21:54:09 +03:00
b9473cca50
docs: CodeBoth для урока 27 «Двойной прыжок» (main+finish)
2026-06-09 21:51:37 +03:00
17417b1b33
feat(g27): полный паритет «Двойной прыжок»
...
JS:
- player.setDoubleJump(true)
- showText 'Жми Space ДВАЖДЫ — двойной прыжок!'
- onTick: y<-3 → respawn + lose
- onMessage 'win' → 'Победа!' + win + confetti
- финиш: onTouch → broadcast 'win'
Lua (паритет):
- __rbxl_set_double_jump(true) — паритет с player.setDoubleJump
- __rbxl_show_text + Sounds
- Heartbeat: player_y < -3 → LoadCharacter + lose
- BindableEvent WinReached
- g27_finish: Touched → WinReached:Fire (fired-флаг)
Shim добавил __rbxl_set_double_jump(bool) → cmd 'player.setDoubleJump'.
2026-06-09 21:50:08 +03:00
19c475f132
docs: CodeBoth для урока 26 «Магнит монет» (main+coin)
2026-06-09 21:48:31 +03:00
2c324fa576
feat(g26): полный паритет «Магнит монет»
...
JS:
- showText 'Подходи к монеткам — они притянутся!'
- ui.score=0 → каждая собранная монета +1
- onMessage 'coin' → score++ + 'coin' sound, при score>=TOTAL победа + confetti
- 8 монет: onTick → dist<6 → tween к игроку (0.5с), dist<1.2 → delete + broadcast
Lua (паритет):
- __rbxl_show_text + Sounds
- __rbxl_score_set(N) — паритет с game.ui.score=N (ui.set id=__score)
- BindableEvent CoinCollected
- 8 g26_coin_N: Heartbeat → dist<6 TweenService к Vector3(px,py+1,pz),
dist<1.2 → ev:Fire + Destroy
Shim добавил __rbxl_score_set(value).
2026-06-09 21:47:20 +03:00
bc1214e600
docs: CodeBoth для урока 25 «Камера-облёт» (main+finish)
2026-06-09 21:45:14 +03:00
189a23ff7c
fix(g25): передаём lookAt-точки чтобы камера вращалась к финишу
...
cameraCutscene без lookAt держит угол постоянным (setTarget не зовётся).
Добавил 3-й arg в __rbxl_camera_cutscene и 4 lookAt-точки указывающие
вдоль пути — камера плавно поворачивается к финишу.
2026-06-09 21:44:14 +03:00
d4b84cf73d
feat(g25): полный паритет «Камера-облёт»
...
JS:
- camera.cutscene 4 точки + segDuration=1.8
- onCutsceneDone → showText 'Вперёд, к зелёному финишу!'
- onMessage 'win' → 'Победа!' + win + confetti
- finish: onTouch → broadcast 'win'
Lua (паритет):
- __rbxl_camera_cutscene('x1,y1,z1, x2,y2,z2, ...', segDuration)
Парсит CSV → отдаёт в GameRuntime cmd 'camera.cutscene'.
- __rbxl_on_cutscene_done(fn) — регистрация cb.
В fireGlobalEvent при p.type='cutsceneDone' фейерим все cb.
- BindableEvent WinReached
- g25_finish: Touched → WinReached:Fire (fired-флаг)
CSV вместо массива объектов — wasmoon через C-boundary
плохо отдаёт массивы таблиц.
2026-06-09 21:41:02 +03:00
2a39fc2b99
docs: CodeBoth для урока 24 «Падающий мост» (main+plank+finish)
2026-06-09 21:38:24 +03:00
5aec627b17
feat(g24): полный паритет «Падающий мост»
...
JS:
- showText 'Беги по мосту — доски рушатся!'
- onTick: p.y < -3 → respawn + 'Упал в пропасть! Снова.' + lose
- onMessage 'win' → 'Победа!' + win + confetti
- 18 досок: onTouch → click sound + delete через 1с
- финиш: onTouch → broadcast 'win'
Lua (паритет):
- __rbxl_show_text + Sounds
- Heartbeat: player_y < -3 → LoadCharacter + lose
- BindableEvent WinReached
- g24_plank_1..18: единый скрипт (IIFE генерит 18 ключей):
Touched → click Sound + Debris:AddItem(part, 1)
- g24_finish: Touched → WinReached:Fire (fired-флаг)
2026-06-09 21:37:05 +03:00
745e50703d
docs: CodeBoth для урока 23 «Переключатели» (main+lever+finish)
2026-06-09 21:34:59 +03:00
eb04da6348
feat(g23): полный паритет «Переключатели»
...
JS:
- showText 'Дёрни рычаги в нужном порядке (E)'
- onMessage 'lever' с {num} → click sound + pressed.push + проверка
совпадения с ORDER=[2,3,1]. Ошибка → reset + 'Неверно!' + lose
Полная последовательность → 'Верно! Дверь открыта' + win + tween двери
- onMessage 'win' → 'Победа!' + win + confetti
- лычаги: onInteract E (distance=3) → broadcast 'lever' {num}
- финиш: onTouch → broadcast 'win'
Lua (паритет):
- __rbxl_show_text + Sounds
- BindableEvents LeverPulled (с num аргументом) + WinReached
- g23_main: проверка порядка + tween двери (Position.Y+6) + CanCollide=false
- 3 g23_lever_N: Heartbeat distance-check (3), __rbxl_hud_set
'[E] Дёрнуть рычаг N' в нижней части экрана.
UserInputService.InputBegan E → LeverPulled:Fire(n)
- g23_finish: Touched → WinReached:Fire (fired-флаг)
2026-06-09 21:33:12 +03:00
791cf2cde5
docs: CodeBoth для урока 22 «Зона опасности» (main+zone+heal+finish)
2026-06-09 21:31:22 +03:00
59769932e5
feat(g22): полный паритет «Зона опасности»
...
JS:
- showText 'Пробеги через красную зону к финишу!'
- every(0.6): если inZone — damage(12) + hit
- onMessage 'zone-enter' → inZone=true + 'Опасно! Беги быстрее!'
- onMessage 'zone-leave' → inZone=false
- onMessage 'win' → 'Победа!' + win + confetti
- g22_zone: onTouch → 'zone-enter', onUntouch → 'zone-leave'
- g22_heal: onTouch → heal(60) + '+60 HP' + pickup + delete
- g22_finish: onTouch → 'win'
Lua (паритет):
- __rbxl_show_text + Sounds
- BindableEvents ZoneEnter/ZoneLeave/WinReached
- Heartbeat-таймер 0.6с для урона пока inZone
- g22_zone: Touched/TouchEnded → ev:Fire
- g22_heal: Touched → __rbxl_heal_player(60) + pickup Sound + Destroy
- g22_finish: Touched → WinReached:Fire
Shim добавил __rbxl_heal_player(amount) → cmd 'player.heal'.
2026-06-09 21:29:32 +03:00
cbc4b87643
docs: CodeBoth для урока 21 «Преследователь» (main+finish)
2026-06-09 21:25:52 +03:00
ea1308d539
feat(g21): полный паритет «Преследователь» + npc.follow/stop/pos в shim
...
JS:
- spawnNpc 'Охотник' speed=4 follow('player')
- onTick: dist(player,enemy) < 1.6 → respawn + 'Пойман!' + lose
- onMessage 'win' → enemy.stop() + 'Победа!' + win + confetti
- g21_finish: onTouch → broadcast 'win'
Lua (паритет):
- __rbxl_show_text + Sounds
- __rbxl_spawn_npc('character-b', ..., 'Охотник', 100, 4)
- __rbxl_npc_follow(ref, 'player') — велим NPC следовать за игроком
- Heartbeat: __rbxl_npc_x/z для расстояния, при <1.6 → LoadCharacter
+ 'Пойман!' + lose Sound (с throttle 2с)
- BindableEvent WinReached + g21_finish.Touched → ev:Fire
- При победе: npc_stop + showText + win + confetti
Shim хелперы:
- __rbxl_npc_follow(ref, target='player')
- __rbxl_npc_stop(ref)
- __rbxl_npc_x/y/z(ref) — позиция NPC
- api.updateNpcPos(localRef, x, y, z) — GameRuntime синкает каждый кадр
GameRuntime.tick собирает позиции всех NPC из npcManager.npcs через
_localToReal и шлёт sb.api.updateNpcPos.
2026-06-09 21:23:53 +03:00
d7478fe311
docs: CodeBoth для урока 20 «Имена над врагами» (g20_main)
2026-06-09 21:20:38 +03:00
58fbc9d6e6
fix(g20): метка height 2.5 — над health-bar
2026-06-09 21:18:50 +03:00
4320c6adeb
fix(g20): уменьшил зазоры метки и health-bar
...
LabelManager использует opts.height как ГАП от верха AABB до плашки,
а не абсолютную высоту. Передавал 3 — метка летела далеко вверх.
Стало 0.3 — небольшой зазор над головой.
Health-bar опустил с y+2.4 до y+1.9 — ближе к голове.
2026-06-09 21:17:16 +03:00
7595668b03
fix(g20): метку HP подняли с 3 до 4 — не перекрывается health-bar
...
Health-bar NPC рендерится на y+2.4 при уроне. Метка height=3 была
слишком близко — health-bar заходил поверх текста. Высота 4 даёт
зазор в ~1.6 над health-bar.
2026-06-09 21:13:38 +03:00