diff --git a/src/community/docsGamesBuildersLua.js b/src/community/docsGamesBuildersLua.js index 7f14797..278f5cb 100644 --- a/src/community/docsGamesBuildersLua.js +++ b/src/community/docsGamesBuildersLua.js @@ -2213,41 +2213,78 @@ end)`, // ═══════════════════════════════════════════════════════════════ // ИГРА 26 — «Магнит монет» // ═══════════════════════════════════════════════════════════════ - 'coin-magnet': { - g26_main: `-- === ИГРА «МАГНИТ МОНЕТ» (Lua) === -local Players = game:GetService("Players") -local RunService = game:GetService("RunService") -local CollectionService = game:GetService("CollectionService") + 'coin-magnet': (function() { + const TOTAL = 8; + const overrides = { + g26_main: `-- === ИГРА «МАГНИТ МОНЕТ» — главный скрипт (Lua) === ${SNIPPET_BROADCAST} +local TOTAL = ${TOTAL} local score = 0 -local ev = getEvent("CoinCollected") -ev.Event:Connect(function() - score = score + 1 - print("Собрано: " .. score) -end) -RunService.Heartbeat:Connect(function(dt) - local player = Players:GetPlayers()[1] - if not player or not player.Character then return end - local hrp = player.Character:FindFirstChild("HumanoidRootPart") - if not hrp then return end - for _, coin in ipairs(CollectionService:GetTagged("magnetcoin")) do - local dist = (coin.Position - hrp.Position).Magnitude - if dist < 8 then - coin.Position = coin.Position + (hrp.Position - coin.Position).Unit * 20 * dt - if dist < 1 then - ev:Fire() - coin:Destroy() - end - end +__rbxl_score_set(0) +__rbxl_show_text("Подходи к монеткам — они притянутся!", 3) + +local coinSound = Instance.new("Sound", workspace) +coinSound.SoundId = "coin"; coinSound.Volume = 0.7 +local winSound = Instance.new("Sound", workspace) +winSound.SoundId = "win"; winSound.Volume = 1 + +-- Монетки шлют ev:Fire() при сборе +local coinEvent = getEvent("CoinCollected") +coinEvent.Event:Connect(function() + score = score + 1 + __rbxl_score_set(score) + coinSound:Play() + if score >= TOTAL then + winSound:Play() + __rbxl_show_text("Победа! Все монетки собраны!", 5) + local px = __rbxl_player_x() + local py = __rbxl_player_y() + local pz = __rbxl_player_z() + __rbxl_spawn_particles("confetti", px, py + 3, pz, 3, 3) end -end) -print("Монетки сами летят к тебе!")`, - g26_coin: `-- === Скрипт магнит-монетки (Lua) === -local CollectionService = game:GetService("CollectionService") -CollectionService:AddTag(script.Parent, "magnetcoin")`, - }, +end)`, + }; + // 8 монеток — каждая со своим Heartbeat: при dist<6 летит к игроку, при dist<1.2 собрана + const coinScript = `-- === Скрипт магнитной монетки (Lua) === +local ReplicatedStorage = game:GetService("ReplicatedStorage") +local RunService = game:GetService("RunService") +local TweenService = game:GetService("TweenService") +local part = script.Parent +local flying = false +local taken = false + +RunService.Heartbeat:Connect(function() + if taken then return end + local cp = part.Position + local px = __rbxl_player_x() + local py = __rbxl_player_y() + local pz = __rbxl_player_z() + -- ждём пока позиция игрока придёт + if px == 0 and py == 0 and pz == 0 then return end + local dx = px - cp.X + local dz = pz - cp.Z + local dist = math.sqrt(dx*dx + dz*dz) + + if dist < 1.2 then + taken = true + local ev = ReplicatedStorage:FindFirstChild("CoinCollected") + if ev then ev:Fire() end + part:Destroy() + return + end + if not flying and dist < 6 then + flying = true + local goal = { Position = Vector3.new(px, py + 1, pz) } + TweenService:Create(part, TweenInfo.new(0.5), goal):Play() + end +end)`; + for (let i = 1; i <= TOTAL; i++) { + overrides['g26_coin_' + i] = coinScript; + } + return overrides; + })(), // ═══════════════════════════════════════════════════════════════ // ИГРА 27 — «Двойной прыжок» diff --git a/src/editor/engine/lua/RobloxShim.js b/src/editor/engine/lua/RobloxShim.js index 5480426..20f8b2f 100644 --- a/src/editor/engine/lua/RobloxShim.js +++ b/src/editor/engine/lua/RobloxShim.js @@ -1965,6 +1965,11 @@ export function registerRobloxShim(lua, opts) { global.set('__rbxl_heal_player', (amount) => { send('player.heal', { amount: Number(amount) || 0 }); }); + // Счёт в углу — паритет с JS game.ui.score = N. null → скрыть. + global.set('__rbxl_score_set', (value) => { + const text = value == null ? null : ('Очки: ' + value); + send('ui.set', { id: '__score', text }); + }); // Камера-облёт — паритет с JS game.camera.cutscene(points, opts). // pointsFlat/lookAtFlat: x1,y1,z1,x2,y2,z2,... — потому что массив // объектов в wasmoon через C-boundary неудобен.