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).
This commit is contained in:
min 2026-06-09 21:47:20 +03:00
parent bc1214e600
commit 2c324fa576
2 changed files with 72 additions and 30 deletions

View File

@ -2213,41 +2213,78 @@ end)`,
// ═══════════════════════════════════════════════════════════════ // ═══════════════════════════════════════════════════════════════
// ИГРА 26 — «Магнит монет» // ИГРА 26 — «Магнит монет»
// ═══════════════════════════════════════════════════════════════ // ═══════════════════════════════════════════════════════════════
'coin-magnet': { 'coin-magnet': (function() {
g26_main: `-- === ИГРА «МАГНИТ МОНЕТ» (Lua) === const TOTAL = 8;
local Players = game:GetService("Players") const overrides = {
local RunService = game:GetService("RunService") g26_main: `-- === ИГРА «МАГНИТ МОНЕТ» — главный скрипт (Lua) ===
local CollectionService = game:GetService("CollectionService")
${SNIPPET_BROADCAST} ${SNIPPET_BROADCAST}
local TOTAL = ${TOTAL}
local score = 0 local score = 0
local ev = getEvent("CoinCollected")
ev.Event:Connect(function()
score = score + 1
print("Собрано: " .. score)
end)
RunService.Heartbeat:Connect(function(dt) __rbxl_score_set(0)
local player = Players:GetPlayers()[1] __rbxl_show_text("Подходи к монеткам — они притянутся!", 3)
if not player or not player.Character then return end
local hrp = player.Character:FindFirstChild("HumanoidRootPart") local coinSound = Instance.new("Sound", workspace)
if not hrp then return end coinSound.SoundId = "coin"; coinSound.Volume = 0.7
for _, coin in ipairs(CollectionService:GetTagged("magnetcoin")) do local winSound = Instance.new("Sound", workspace)
local dist = (coin.Position - hrp.Position).Magnitude winSound.SoundId = "win"; winSound.Volume = 1
if dist < 8 then
coin.Position = coin.Position + (hrp.Position - coin.Position).Unit * 20 * dt -- Монетки шлют ev:Fire() при сборе
if dist < 1 then local coinEvent = getEvent("CoinCollected")
ev:Fire() coinEvent.Event:Connect(function()
coin:Destroy() 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
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 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
end) end)`;
print("Монетки сами летят к тебе!")`, for (let i = 1; i <= TOTAL; i++) {
g26_coin: `-- === Скрипт магнит-монетки (Lua) === overrides['g26_coin_' + i] = coinScript;
local CollectionService = game:GetService("CollectionService") }
CollectionService:AddTag(script.Parent, "magnetcoin")`, return overrides;
}, })(),
// ═══════════════════════════════════════════════════════════════ // ═══════════════════════════════════════════════════════════════
// ИГРА 27 — «Двойной прыжок» // ИГРА 27 — «Двойной прыжок»

View File

@ -1965,6 +1965,11 @@ export function registerRobloxShim(lua, opts) {
global.set('__rbxl_heal_player', (amount) => { global.set('__rbxl_heal_player', (amount) => {
send('player.heal', { amount: Number(amount) || 0 }); 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). // Камера-облёт — паритет с JS game.camera.cutscene(points, opts).
// pointsFlat/lookAtFlat: x1,y1,z1,x2,y2,z2,... — потому что массив // pointsFlat/lookAtFlat: x1,y1,z1,x2,y2,z2,... — потому что массив
// объектов в wasmoon через C-boundary неудобен. // объектов в wasmoon через C-boundary неудобен.