fix(g16): урон только когда игрок РЕАЛЬНО в лаве (не над островком)
Раньше: фильтр по Y-капсулы не работал — игрок стоит на островке на realPos.y=1.54 > порога 1.35, фильтр пропускал. Стало: проверяем где игрок по X/Z. Если над островком (любой из 6) или над финишной площадкой — пропускаем урон. Иначе — урон каждый кадр пока Touched активно (RunService.Heartbeat). У damage есть i-frames ~0.5с так что урон ~2/сек. Также: переход с Touched-разово на Heartbeat-постоянно. Раньше Touched срабатывал только при ВХОДЕ в лаву — если игрок стоит в лаве долго, TouchEnded не вызывался, и урон шёл только раз. Теперь Touched/TouchEnded выставляют inLava-флаг, Heartbeat считает урон каждый кадр.
This commit is contained in:
parent
f0f739071a
commit
2979104931
@ -1396,21 +1396,56 @@ end)`,
|
||||
g16_lava: `-- === Скрипт лавы (Lua) ===
|
||||
-- Игрок коснулся лавы — урон. У damage есть защита (i-frames),
|
||||
-- так что урон не каждый кадр, а раз в ~0.5 секунды.
|
||||
-- ВАЖНО: лава-зона может пересекаться с островками по AABB. Проверяем
|
||||
-- что игрок РЕАЛЬНО внизу (стоит в лаве), а не на островке выше.
|
||||
-- ВАЖНО: проверяем что игрок НЕ над островком (по X/Z),
|
||||
-- иначе урон срабатывает на островке из-за пересечения AABB.
|
||||
local RunService = game:GetService("RunService")
|
||||
local part = script.Parent
|
||||
local hitSound = Instance.new("Sound", part)
|
||||
hitSound.SoundId = "hit"; hitSound.Volume = 0.7
|
||||
|
||||
-- Координаты островков (из builder): { x, z }
|
||||
local ISLES = {
|
||||
{0, 5}, {3, 9}, {-2, 13}, {2, 17}, {-3, 21}, {1, 25},
|
||||
}
|
||||
local ISLE_HW = 1.4 -- половина ширины островка sx=2.4/2 + небольшой запас
|
||||
local FINISH_X, FINISH_Z = -0.5, 29
|
||||
local FINISH_HW, FINISH_HD = 3, 2.5
|
||||
|
||||
local function isOverSafeSpot()
|
||||
local px = __rbxl_player_x()
|
||||
local pz = __rbxl_player_z()
|
||||
-- Островки
|
||||
for _, isle in ipairs(ISLES) do
|
||||
if math.abs(px - isle[1]) <= ISLE_HW
|
||||
and math.abs(pz - isle[2]) <= ISLE_HW then
|
||||
return true
|
||||
end
|
||||
end
|
||||
-- Финишная площадка
|
||||
if math.abs(px - FINISH_X) <= FINISH_HW
|
||||
and math.abs(pz - FINISH_Z) <= FINISH_HD then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- Проверяем каждый кадр пока игрок касается лавы — наносим урон если он
|
||||
-- НЕ над безопасным местом. Touched нам не нужен — лучше Heartbeat-проверка.
|
||||
local inLava = false
|
||||
part.Touched:Connect(function(hit)
|
||||
local h = hit.Parent and hit.Parent:FindFirstChild("Humanoid")
|
||||
if not h then return end
|
||||
-- Игрок на безопасной высоте (на островке/финише) — не урон.
|
||||
-- Лава-зона на y=1, верх y=1.3. Островки на y=1.2 верх y=1.5.
|
||||
-- Игрок СТОИТ на островке когда его _pos.y - halfH (= нижняя точка
|
||||
-- капсулы) ~= верх островка. Стоит на лаве когда нижняя точка ниже 1.3.
|
||||
local py = __rbxl_player_y()
|
||||
if py >= 1.35 then return end -- стоит на островке/финише — пропускаем
|
||||
inLava = true
|
||||
end)
|
||||
part.TouchEnded:Connect(function(hit)
|
||||
local h = hit.Parent and hit.Parent:FindFirstChild("Humanoid")
|
||||
if not h then return end
|
||||
inLava = false
|
||||
end)
|
||||
|
||||
RunService.Heartbeat:Connect(function()
|
||||
if not inLava then return end
|
||||
if isOverSafeSpot() then return end -- стоит над островком/финишем
|
||||
__rbxl_damage_player(20)
|
||||
hitSound:Play()
|
||||
end)`,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user