Menu
CoddyTech

The Monster Comes

Lesson 9 of 25 in Coddy's Roblox Game: Escape the Dark course.

Now the monster. ServerStorage.Shadow is a tall dark model with a Humanoid, so it walks with Humanoid:MoveTo like any NPC.

When room Settings.MonsterFrom (4) opens, it comes in behind the players: at the entrance of the room two before the newest. A loop over the rooms finds that one by its Number:

for _, room in rooms:GetChildren() do
	if room:GetAttribute("Number") == count - 2 then
		behind = room
	end
end

The model's pivot is in its middle, so it goes 3.1 studs above the entrance to stand on the floor. It keeps the speed of Settings.MonsterSpeed on its Humanoid's WalkSpeed.

challenge icon

Challenge

Medium

The monster comes in behind you.

  1. Add local monster = nil at the top.
  2. Above addRoom, write spawnMonster(): clone ServerStorage.Shadow into monster at the Entrance.CFrame + Vector3.new(0, 3.1, 0) of room count - 2; WalkSpeed Settings.MonsterSpeed; parent it to workspace.
  3. In addRoom, call it when count == Settings.MonsterFrom.

Press Play and get through room 3: the Shadow stands two rooms behind you. Then Check.

Try it yourself

local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local Lighting = game:GetService("Lighting")
local TweenService = game:GetService("TweenService")
local Settings = require(game.ReplicatedStorage.Settings)

local rooms = workspace.Rooms
local lastRoom = rooms.Lobby -- the newest room
local count = 0 -- rooms made so far

-- Night falls: no sun, a little light everywhere, and fog
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")

-- A tool a player carries: in their hand, or in their Backpack
local function findTool(player, name)
	return (player.Character and player.Character:FindFirstChild(name)) or player.Backpack:FindFirstChild(name)
end

-- Swing a door open on its hinge
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

-- Lesson 9: The Monster Comes goes here

local addRoom -- written below: a door adds a room, and a room has a door

-- What a door does when a player opens it
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)

-- Walking into a room: it becomes the player's Room, and their checkpoint
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)

-- A new room at the exit of the newest one
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)
	-- a locked room keeps its key inside
	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
	-- keep the newest room and KeepRooms behind it
	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
	return room
end

-- Every player: Room on the leaderboard, and a flashlight every life
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.Parent = player.Backpack
		local beam = flashlight.Handle.Beam
		flashlight.Activated:Connect(function()
			beam.Enabled = not beam.Enabled
		end)
	end)
end)

All lessons in Roblox Game: Escape the Dark

Practice on your own: Roblox playground