[Puzzle Script] Multi-philosopher stone puzzle.

Ask for help about creating mods and scripts for Grimrock 2 or share your tips, scripts, tools and assets with other modders here. Warning: forum contains spoilers!
Post Reply
GoldenShadowGS
Posts: 168
Joined: Thu Oct 30, 2014 1:56 am

[Puzzle Script] Multi-philosopher stone puzzle.

Post by GoldenShadowGS »

So I have made a puzzle with five pushable stones. When you push one, the other 4 move in the same direction. I named the stones "templeblock1", "templeblock2" etc..
There are some checks since doing this method of using clickNorth,clicksouth is messy and you can push the blocks sideways if you click on the sides. so I had to do a check to make sure the player is in front of the stone they are pushing. I can't use the setFrontFacing(boolean) on the clickable since the front is determined by the base object's facing, not the facing of side you click on.
I added another check so a stone will not try to move if it will be blocked by another stone. there is some weirdness. Depending on the order on the entity list, two adjacent stones moving the same way will either both move or only one will move and the 2nd be blocked by the first.

All of the checks are to assure there is no weirdness and the puzzle is consistent.

I needed 4 push direction functions because I couldn't pass a (dir) argument from the addconnector to updateblock(), so I just made a separate function for each direction.

Code: Select all

--autoexec adds connectors to all the stones' clickable sides
for i = 1,5 do
	local block = findEntity("templeblock"..i)
	block.clickNorth:addConnector("onClick", "script_entity_28", "updateblock0")
	block.clickEast:addConnector("onClick", "script_entity_28", "updateblock1")
	block.clickSouth:addConnector("onClick", "script_entity_28", "updateblock2")
	block.clickWest:addConnector("onClick", "script_entity_28", "updateblock3")
end

function updateblock0(self)
--Push north, checks if the party is south of the clickable just clicked. This prevents moving a stone north from the west or east by clicking on the "clickNorth" edge from the side. The self arg comes from the stone you just clicked.
	if self.go.x == party.x and self.go.y + 1 == party.y then
		for i = 1,5 do
             --go through each stone to see If its eligible to be moved.
			local blocked = false
			local ablock = findEntity("templeblock"..i)
			local x = ablock.x
			local y = ablock.y
			for a = 1,5 do 
                       --checks all 5 stones and sets variable "blocked" to true if this stone has another stone exactly one tile north of itself
				local bblock = findEntity("templeblock"..a)
				local x2 = bblock.x
				local y2 = bblock.y
				if y - 1 == y2 and x == x2 then
					blocked = true
				end
			end
                --move the stone if it is not blocked; "push(0)" is north
			if blocked == false then
				ablock.pushableblock:push(0)
			end
		end
	end
end

function updateblock1(self)
	if self.go.x - 1 == party.x and self.go.y == party.y then
		for i = 1,5 do
			local blocked = false
			local ablock = findEntity("templeblock"..i)
			local x = ablock.x
			local y = ablock.y
			for a = 1,5 do 
				local bblock = findEntity("templeblock"..a)
				local x2 = bblock.x
				local y2 = bblock.y
				if y == y2 and x + 1 == x2 then
					blocked = true
				end
			end
			if blocked == false then
				ablock.pushableblock:push(1)
			end
		end
	end
end

function updateblock2(self)
	if self.go.x == party.x and self.go.y - 1 == party.y then
		for i = 1,5 do
			local blocked = false
			local ablock = findEntity("templeblock"..i)
			local x = ablock.x
			local y = ablock.y
			for a = 1,5 do 
				local bblock = findEntity("templeblock"..a)
				local x2 = bblock.x
				local y2 = bblock.y
				if y + 1 == y2 and x == x2 then
					blocked = true
				end
			end
			if blocked == false then
				ablock.pushableblock:push(2)
			end
		end
	end
end

function updateblock3(self)
	if self.go.x + 1 == party.x and self.go.y == party.y then
		for i = 1,5 do
			local blocked = false
			local ablock = findEntity("templeblock"..i)
			local x = ablock.x
			local y = ablock.y
			for a = 1,5 do 
				local bblock = findEntity("templeblock"..a)
				local x2 = bblock.x
				local y2 = bblock.y
				if y == y2 and x - 1 == x2 then
					blocked = true
				end
			end
			if blocked == false then
				ablock.pushableblock:push(3)
			end
		end
	end
end
There are some interesting properties of this setup. You can not get all of the stones stuck in a corner as long as you have access to all 4 sides of at least one stone, you can undo most moves. Stones will not move if the player(and I assume monster) is standing on the tile they are pushed onto. Pushing a chain of stones along their axis only moves the one at the very end. Pushing a chain from perpendicular will move the entire column sideways. They are still limited to pushable block floors and will not move if you try to push them off the platform.
Post Reply