feat(g15): полный паритет «Тир» + ClickDetector в shim
JS:
- 8 мишеней-сфер на постаментах
- ui.score, showText 'Кликай по красным мишеням!'
- target: onClick → explosion particles + delete + broadcast 'hit'
- main: onMessage 'hit' → score++ + hit sound + при 8 победа+confetti
Lua-shim расширение:
- Instance.new('ClickDetector') создаёт инстанс с MouseClick signal
- Когда clickDet.Parent = part → Proxy.set регистрирует
part._clickDetector = clickDet
- fireTargetEvent при kind='click' фейерит part._clickDetector.MouseClick.Fire
Lua-скрипт игры 15:
- ScreenGui 'Мишени: N / 8'
- BindableEvent TargetHit
- 8 g15_target_N (ids 2,4,6,8,10,12,14,16): ClickDetector с
MaxActivationDistance=50 → MouseClick → spawn explosion + Destroy + Fire
- main: hit Sound, при 8 — win Sound + showText + confetti
This commit is contained in:
parent
2e1ee87ed6
commit
8abbde9d67
@ -1277,38 +1277,83 @@ end)`;
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
// ИГРА 15 — «Тир»
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
'shooting-range': {
|
||||
g15_main: `-- === ИГРА «ТИР» (Lua) ===
|
||||
local UserInputService = game:GetService("UserInputService")
|
||||
local Players = game:GetService("Players")
|
||||
'shooting-range': (function() {
|
||||
// Мишени имеют id 2, 4, 6, 8, 10, 12, 14, 16 (постамент → нечётный, мишень → чётный)
|
||||
const TARGET_IDS = [2, 4, 6, 8, 10, 12, 14, 16];
|
||||
const TOTAL = TARGET_IDS.length;
|
||||
const overrides = {
|
||||
g15_main: `-- === ИГРА «ТИР» — главный скрипт (Lua) ===
|
||||
${SNIPPET_BROADCAST}
|
||||
|
||||
local Players = game:GetService("Players")
|
||||
local player = Players.LocalPlayer
|
||||
local score = 0
|
||||
print("Стреляй ЛКМ по красным шарам!")
|
||||
local TOTAL = ${TOTAL}
|
||||
local won = false
|
||||
|
||||
local ev = getEvent("TargetHit")
|
||||
ev.Event:Connect(function()
|
||||
__rbxl_show_text("Кликай по красным мишеням!", 3)
|
||||
|
||||
-- Счётчик в правом верхнем углу
|
||||
local screenGui = Instance.new("ScreenGui", player.PlayerGui)
|
||||
local label = Instance.new("TextLabel", screenGui)
|
||||
label.Size = UDim2.new(0, 220, 0, 50)
|
||||
label.Position = UDim2.new(1, -240, 0, 20)
|
||||
label.BackgroundColor3 = Color3.fromRGB(0, 0, 0)
|
||||
label.BackgroundTransparency = 0.4
|
||||
label.TextColor3 = Color3.fromRGB(255, 100, 100)
|
||||
label.TextScaled = true
|
||||
label.Font = Enum.Font.SourceSansBold
|
||||
label.Text = "Мишени: 0 / " .. TOTAL
|
||||
|
||||
local hitSound = Instance.new("Sound", workspace)
|
||||
hitSound.SoundId = "hit"; hitSound.Volume = 0.7
|
||||
local winSound = Instance.new("Sound", workspace)
|
||||
winSound.SoundId = "win"; winSound.Volume = 1
|
||||
|
||||
local hitEvent = getEvent("TargetHit")
|
||||
hitEvent.Event:Connect(function()
|
||||
if won then return end
|
||||
score = score + 1
|
||||
print("Попал! Очки: " .. score)
|
||||
end)
|
||||
|
||||
-- ЛКМ — пускаем луч из камеры
|
||||
UserInputService.InputBegan:Connect(function(input, gp)
|
||||
if gp then return end
|
||||
if input.UserInputType ~= Enum.UserInputType.MouseButton1 then return end
|
||||
local player = Players.LocalPlayer
|
||||
local mouse = player:GetMouse()
|
||||
local target = mouse.Target
|
||||
if target and target:GetAttribute("IsTarget") then
|
||||
local hitEv = workspace:FindFirstChild("TargetHit") or ev
|
||||
ev:Fire()
|
||||
target:Destroy()
|
||||
label.Text = "Мишени: " .. score .. " / " .. TOTAL
|
||||
hitSound:Play()
|
||||
if score >= TOTAL then
|
||||
won = true
|
||||
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)`,
|
||||
g15_target: `-- === Скрипт мишени (Lua) ===
|
||||
};
|
||||
// Скрипт каждой мишени — ClickDetector + взрыв искр + сообщение
|
||||
const targetScript = `-- === Скрипт мишени (Lua) ===
|
||||
-- Клик ЛКМ по мишени = выстрел. ClickDetector ловит клик в 3D.
|
||||
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
||||
local part = script.Parent
|
||||
part:SetAttribute("IsTarget", true)`,
|
||||
},
|
||||
local hit = false
|
||||
|
||||
local clickDet = Instance.new("ClickDetector", part)
|
||||
clickDet.MaxActivationDistance = 50
|
||||
|
||||
clickDet.MouseClick:Connect(function()
|
||||
if hit then return end
|
||||
hit = true
|
||||
-- Взрыв искр на месте мишени
|
||||
local pos = part.Position
|
||||
__rbxl_spawn_particles("explosion", pos.X, pos.Y, pos.Z, 0.5, 1)
|
||||
-- Сообщаем главному скрипту
|
||||
local ev = ReplicatedStorage:FindFirstChild("TargetHit")
|
||||
if ev then ev:Fire() end
|
||||
-- Мишень исчезает
|
||||
part:Destroy()
|
||||
end)`;
|
||||
for (const tid of TARGET_IDS) {
|
||||
overrides['g15_target_' + tid] = targetScript;
|
||||
}
|
||||
return overrides;
|
||||
})(),
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
// ИГРА 16 — «Лавовый пол»
|
||||
|
||||
@ -436,6 +436,11 @@ function newInstance(className, name) {
|
||||
value.Children.push(proxyRef);
|
||||
try { value.ChildAdded && value.ChildAdded.Fire(proxyRef); } catch (_) {}
|
||||
}
|
||||
// Спец-регистрация для ClickDetector — чтобы клик по Part
|
||||
// мог сфейерить MouseClick через fireTargetEvent.
|
||||
if (t.ClassName === 'ClickDetector' && value) {
|
||||
try { value._clickDetector = proxyRef; } catch (_) {}
|
||||
}
|
||||
try { t.AncestryChanged && t.AncestryChanged.Fire(proxyRef, value); } catch (_) {}
|
||||
return true;
|
||||
}
|
||||
@ -1387,6 +1392,15 @@ export function registerRobloxShim(lua, opts) {
|
||||
inst.Scale = new RbxVector3(1, 1, 1);
|
||||
inst.Offset = new RbxVector3(0, 0, 0);
|
||||
inst.VertexColor = new RbxVector3(1, 1, 1);
|
||||
} else if (className === 'ClickDetector') {
|
||||
// ClickDetector — клик по 3D-объекту (нужен Тиру и т.п.).
|
||||
// Регистрация в part._clickDetector происходит автоматически
|
||||
// через Proxy.set когда юзер делает clickDet.Parent = part.
|
||||
inst = newInstance('ClickDetector', 'ClickDetector');
|
||||
inst.MouseClick = makeSignal();
|
||||
inst.MouseHoverEnter = makeSignal();
|
||||
inst.MouseHoverLeave = makeSignal();
|
||||
inst.MaxActivationDistance = 32;
|
||||
} else if (className === 'BindableEvent') {
|
||||
inst = newInstance('BindableEvent', 'BindableEvent');
|
||||
inst.Event = makeSignal();
|
||||
@ -2164,6 +2178,18 @@ export function registerRobloxShim(lua, opts) {
|
||||
part.Touched.Fire(hrp);
|
||||
} else if (p.kind === 'untouch' || p.kind === 'untouched') {
|
||||
part.TouchEnded.Fire(hrp);
|
||||
} else if (p.kind === 'click') {
|
||||
// ClickDetector создаётся лениво — стрельба по 3D-объектам.
|
||||
// Юзер делает: part.ClickDetector = Instance.new('ClickDetector', part)
|
||||
// + clickDet.MouseClick:Connect(fn). Здесь фейерим сигнал.
|
||||
try {
|
||||
const cd = part._clickDetector;
|
||||
if (cd && cd.MouseClick) cd.MouseClick.Fire(localPlayer);
|
||||
} catch (_) {}
|
||||
// Также фейерим Part.Clicked если есть (наш расширенный API).
|
||||
try {
|
||||
if (part.Clicked) part.Clicked.Fire();
|
||||
} catch (_) {}
|
||||
}
|
||||
},
|
||||
fireGlobalEvent(p) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user