Mengambil Baterai
Pelajaran 18 dari 25 dalam kursus Game Roblox: Kabur dari Kegelapan di Coddy.
Baterai yang hanya terkuras membuat setiap permainan berakhir dalam gelap. Beberapa ruangan memiliki BatterySpot, dan baterai di sana mengisi ulang hingga Settings.BatteryRefill, tidak pernah melebihi kapasitas penuh:
flashlight:SetAttribute("Battery", math.min(Settings.BatteryMax, flashlight:GetAttribute("Battery") + 30))Baterai hanya digunakan sekali. Prompt-nya bisa aktif dua kali dalam waktu singkat, jadi periksa apakah baterai masih ada di dalam game (battery.Parent) sebelum menggunakannya.
Tantangan
SulitLetakkan baterai di beberapa ruangan.
- Di
addRoom, ruangan denganBatterySpotmendapat klonaServerStorage.Batterydenganbattery.CFrame = batterySpot.CFrame, yang dijadikan anak dari ruangan tersebut. Prompt-nya menambahkanSettings.BatteryRefillke senter pemain, paling banyak hinggaSettings.BatteryMax, lalu menghancurkan baterai.
Tekan tombol “Main” dan ambil baterai di ruangan 1: baterainya menghilang dan HUD bertambah. Lalu tekan tombol “Periksa”.
Coba sendiri
local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local Lighting = game:GetService("Lighting")
local TweenService = game:GetService("TweenService")
local PathfindingService = game:GetService("PathfindingService")
local Settings = require(game.ReplicatedStorage.Settings)
local rooms = workspace.Rooms
local lastRoom = rooms.Lobby -- ruangan terbaru
local count = 0 -- jumlah ruangan yang sudah dibuat
local monster = nil
-- Malam tiba: tanpa matahari, sedikit cahaya di mana-mana, dan kabut
Lighting.ClockTime = Settings.ClockTime
Lighting.Ambient = Settings.Ambient
Lighting.OutdoorAmbient = Settings.Ambient
Lighting.FogColor = Color3.new(0, 0, 0)
Lighting.FogEnd = Settings.FogEnd
print("Lights out")
-- Alat yang dibawa pemain: di tangan atau di Backpack
local function findTool(player, name)
return (player.Character and player.Character:FindFirstChild(name)) or player.Backpack:FindFirstChild(name)
end
-- Baterai senter berkurang saat menyala, lalu senter padam saat habis
task.spawn(function()
while true do
task.wait(0.25)
for _, player in Players:GetPlayers() do
local flashlight = player.Character and player.Character:FindFirstChild("Flashlight")
if flashlight and flashlight.Handle.Beam.Enabled then
local battery = math.max(0, flashlight:GetAttribute("Battery") - Settings.BatteryDrain * 0.25)
flashlight:SetAttribute("Battery", battery)
if battery == 0 then
flashlight.Handle.Beam.Enabled = false
end
end
end
end
end)
-- Ayunkan pintu hingga terbuka pada engselnya
local function openDoor(door)
door:SetAttribute("Open", true)
door.Panel.Prompt.Enabled = false
local hinge, panel = door.Hinge, door.Panel
local goal = hinge.CFrame * CFrame.Angles(0, math.rad(90), 0) * hinge.CFrame:ToObjectSpace(panel.CFrame)
TweenService:Create(panel, TweenInfo.new(0.6), { CFrame = goal }):Play()
end
-- Pemain hidup terdekat yang bisa ditangkap (tidak bersembunyi), dalam jangkauan MonsterSight, beserta jaraknya
local function nearestCharacter(position)
local best, bestDistance = nil, Settings.MonsterSight
for _, player in Players:GetPlayers() do
local character = player.Character
local root = character and character:FindFirstChild("HumanoidRootPart")
if root and character.Humanoid.Health > 0 and not character:GetAttribute("Hidden") then
local distance = (root.Position - position).Magnitude
if distance < bestDistance then
best, bestDistance = character, distance
end
end
end
return best, bestDistance
end
-- Bisakah monster melihat karakter ini? Sinar dari kepalanya mengenai karakter tersebut
local function canSee(shadow, character)
local from = shadow.Head.Position
local params = RaycastParams.new()
params.FilterDescendantsInstances = { shadow }
local hit = workspace:Raycast(from, character.HumanoidRootPart.Position - from, params)
return hit ~= nil and hit.Instance:IsDescendantOf(character)
end
-- Berjalan menuju suatu titik: lurus jika jalan bebas, jika tidak, ikuti jalur
local function walkToward(shadow, goal, path)
local root = shadow.HumanoidRootPart
local params = RaycastParams.new()
params.FilterDescendantsInstances = { shadow }
local hit = workspace:Raycast(root.Position, goal - root.Position, params)
if not hit or hit.Instance.Parent:FindFirstChildOfClass("Humanoid") then
shadow.Humanoid:MoveTo(goal)
return
end
path:ComputeAsync(root.Position, goal)
local points = path:GetWaypoints()
if path.Status == Enum.PathStatus.Success and points[2] then
shadow.Humanoid:MoveTo(points[2].Position)
end
end
-- Tengah ruangan yang berjarak `back` ruangan sebelum ruangan tempat pemain berada (ruangan
-- sebelum yang terbaru), untuk patroli monster
local function patrolPoint(back)
for _, room in rooms:GetChildren() do
if room:GetAttribute("Number") == count - 1 - back then
return (room.Entrance.CFrame * CFrame.new(0, 3.1, -12)).Position
end
end
return nil
end
-- Cara monster berpikir: setiap seperempat detik, mengejar seseorang
local function runMonster(shadow)
local humanoid = shadow.Humanoid
local root = shadow.HumanoidRootPart
local path = PathfindingService:CreatePath()
local lastSeen = nil -- tempat terakhir monster melihat seseorang
local back = 0 -- rute patrolinya: 0 adalah ruangan pemain, 2 adalah dua ruangan di belakangnya
while shadow.Parent do
local character = nearestCharacter(root.Position)
if character and canSee(shadow, character) then
lastSeen = character.HumanoidRootPart.Position
else
character = nil
end
if character and (character.HumanoidRootPart.Position - root.Position).Magnitude <= Settings.CatchDistance then
-- tertangkap: pemain kalah, dan monster pergi sampai pintu berikutnya
character.Humanoid.Health = 0
shadow:Destroy()
monster = nil
return
end
local goal = character and character.HumanoidRootPart.Position or lastSeen
if goal then
walkToward(shadow, goal, path)
-- monster tiba di tempat terakhir melihatmu, tetapi kamu tidak ada di sana: monster menyerah
if not character and ((goal - root.Position) * Vector3.new(1, 0, 1)).Magnitude < 1.5 then
lastSeen = nil
end
else
-- tak ada yang terlihat: monster berpatroli bolak-balik
local point = patrolPoint(back) or patrolPoint(0)
if point then
walkToward(shadow, point, path)
if ((point - root.Position) * Vector3.new(1, 0, 1)).Magnitude < 2 then
back = back == 0 and 2 or 0
end
end
end
task.wait(0.25)
end
end
-- Monster muncul di belakangmu: di pintu masuk ruangan dua ruangan sebelum yang terbaru
local function spawnMonster()
local behind = nil
for _, room in rooms:GetChildren() do
if room:GetAttribute("Number") == count - 2 then
behind = room
end
end
if not behind then
return
end
monster = ServerStorage.Shadow:Clone()
monster:PivotTo(behind.Entrance.CFrame + Vector3.new(0, 3.1, 0))
monster.Humanoid.WalkSpeed = Settings.MonsterSpeed
monster.Parent = workspace
task.spawn(runMonster, monster)
end
local addRoom -- ditulis di bawah: pintu menambahkan ruangan, dan ruangan memiliki pintu
-- Apa yang dilakukan pintu saat pemain membukanya
local function setupDoor(door)
door.Panel.Prompt.Triggered:Connect(function(player)
if door:GetAttribute("Open") then
return
end
if door:GetAttribute("Locked") then
local key = findTool(player, "Key")
if not key then
return
end
key:Destroy()
door:SetAttribute("Locked", nil)
end
if door.Parent == lastRoom then
addRoom()
end
openDoor(door)
end)
end
setupDoor(workspace.Rooms.Lobby.Door)
-- Saat pemain masuk ke ruangan: ruangan itu menjadi Room pemain dan checkpoint-nya
local function setupEntry(room)
room.Entry.Touched:Connect(function(hit)
local player = Players:GetPlayerFromCharacter(hit.Parent)
if player then
local number = room:GetAttribute("Number")
player.leaderstats.Room.Value = number
player.RespawnLocation = room.Checkpoint
end
end)
end
setupEntry(workspace.Rooms.Lobby)
-- Lemari: tekan E untuk bersembunyi di dalam, tekan E lagi untuk keluar
local function setupCloset(closet)
closet.Front.Prompt.Triggered:Connect(function(player)
local character = player.Character
if character:GetAttribute("Hidden") then
character:PivotTo(closet.Front.CFrame * CFrame.new(-3, -1, 0) * CFrame.Angles(0, math.rad(90), 0))
character:SetAttribute("Hidden", nil)
else
character:PivotTo(closet.Inside.CFrame + Vector3.new(0, 2.5, 0))
character:SetAttribute("Hidden", true)
end
end)
end
-- Ruangan baru di pintu keluar ruangan terbaru
function addRoom()
count += 1
local name = Settings.Order[(count - 1) % #Settings.Order + 1]
if count >= Settings.RoomsToEscape then
name = "Exit"
end
local room = ServerStorage.Rooms[name]:Clone()
room:PivotTo(lastRoom.Exit.CFrame)
room:SetAttribute("Number", count)
room.Sign.SurfaceGui.Number.Text = "Room " .. count
room.Parent = rooms
lastRoom = room
setupDoor(room.Door)
setupEntry(room)
-- ruangan terkunci menyimpan kuncinya di dalam
local keySpot = room:FindFirstChild("KeySpot")
if keySpot then
local key = ServerStorage.Key:Clone()
key.Handle.CFrame = keySpot.CFrame
key.Parent = room
key.Handle.Prompt.Triggered:Connect(function(player)
key.Handle.Prompt.Enabled = false
key.Parent = player.Backpack
end)
end
local closet = room:FindFirstChild("Closet")
if closet then
setupCloset(closet)
end
-- Pelajaran 18: Battery Pickups ditambahkan di sini
-- pertahankan ruangan terbaru dan KeepRooms ruangan sebelumnya
for _, old in rooms:GetChildren() do
local number = old:GetAttribute("Number")
if number < count - Settings.KeepRooms then
print("Room " .. number .. " is gone")
old:Destroy()
end
end
if count >= Settings.MonsterFrom and not monster then
spawnMonster()
end
return room
end
-- Setelah keluar dari lemari, kamu tidak lagi bersembunyi
task.spawn(function()
while true do
task.wait(0.25)
for _, player in Players:GetPlayers() do
local character = player.Character
if character and character:GetAttribute("Hidden") then
local closest = math.huge
for _, inside in workspace.Rooms:GetDescendants() do
if inside.Name == "Inside" then
closest = math.min(closest, (inside.Position - character.HumanoidRootPart.Position).Magnitude)
end
end
if closest > 4 then
character:SetAttribute("Hidden", nil)
end
end
end
end
end)
-- Setiap pemain: Room di papan peringkat dan senter setiap kali hidup kembali
Players.PlayerAdded:Connect(function(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local room = Instance.new("IntValue")
room.Name = "Room"
room.Parent = leaderstats
player.CharacterAdded:Connect(function()
local flashlight = ServerStorage.Flashlight:Clone()
flashlight:SetAttribute("Battery", Settings.BatteryMax)
flashlight.Parent = player.Backpack
local beam = flashlight.Handle.Beam
flashlight.Activated:Connect(function()
if beam.Enabled then
beam.Enabled = false
elseif flashlight:GetAttribute("Battery") > 0 then
beam.Enabled = true
end
end)
end)
end)
Semua pelajaran di Game Roblox: Kabur dari Kegelapan
4Melarikan Diri
BateraiLatihan sendiri: Playground Roblox