Page 1 of 1

[Script/puzzle]Random lever movement that has to be repeated

Posted: Sun Nov 02, 2014 12:20 am
by Blichew
Hi - so I've created a lever-based riddle lately which I wanted to share. If you make any interesting changes to the script, please post them here :)

I. PIC
II. Entity list
III. Script description - lever placement and function description
IV. Connections and other editor stuff
V. Ideas
VI. Whole contents of script entity (for TL;DR and copy-paste)

I. PIC - Here's what it looks like. At the beginning all levers are blocked, button is accessible (to present new random sequence):
SpoilerShow
Image
II. Here's what you need and what names you should give to entities to just copy-paste script:
SpoilerShow
1. 6x lever and 1x wall_button placed exactly on one wall, facing East. IDs: lr_1 lr_2 lr_3 lr_4 lr_5 lr_6 lr_button
2. 1x dungeon_wall_text placed on the tile next to it. ID: lr_wt. Text -

Code: Select all

Press the button above
to start playing the sequence
3. 1x counter. ID: lr_counter
4. 1x script_entity. ID: lr_script
5. 1x timer. ID: lr_timer - Interval set on 0.5. DISABLED at start.
6. Treasure (not included in script:) )
III. Everything is in written in the lr_script:
1. Button placement (to fit them on the same wall along with wall text) and global flag for information if the riddle is already set. Tricky part is that you have to figure out the numbers yourself. For reference: I had my levers placed X:8, Y:22, Z:0:
SpoilerShow

Code: Select all

lr_1:setWorldPosition(26.9999,-0.49,29.5,0)
lr_2:setWorldPosition(26.9999,-0.49,29.1,0)
lr_3:setWorldPosition(26.9999,-0.49,28.7,0)
lr_4:setWorldPosition(26.9999,-0.49,28.3,0)
lr_5:setWorldPosition(26.9999,-0.49,27.9,0)
lr_6:setWorldPosition(26.9999,-0.49,27.5,0)
lr_button:setWorldPositionY(0.6)

riddleSet = 0
2. Functions:
2.1 createRiddle() - responsible for chosing random lever (six times) and saving the combination in the array. Every time a lever is chosen it's toggled via the timer so the sequence actually plays.
SpoilerShow

Code: Select all

function createRiddle()
	lr_button.clickable:disable()
	if riddle_index < 7 then
		riddle[riddle_index] = math.random(6)
		local lever = findEntity("lr_"..riddle[riddle_index])
		lever.lever:toggle()
	else
		if riddle_index > 9 then
			for i=1,6 do
				local l = findEntity("lr_"..i)
				if l.lever:isActivated() then
					l.lever:toggle()
				end
			end
			hudPrint("Please enter correct combination to proceed. "..lr_trials.counter:getValue().." attempt(s) left")
			lr_wt.walltext:setWallText(lr_trials.counter:getValue().." attempt(s) left")
			--print("COMB: "..riddle[1]..", "..riddle[2]..", "..riddle[3]..", "..riddle[4]..", "..riddle[5]..", "..riddle[6]..".")
			lr_timer.timer:stop()
			lr_button.clickable:disable()
			riddleSet = 1
		end
	end
	riddle_index = riddle_index + 1
end
2.2 resetRiddle() - reset globals and enable all the levers for player to toggle after the button is pressed
SpoilerShow

Code: Select all

function resetRiddle()
	riddle = {}
	riddle_index = 1
	check_index = 1
	riddleSet = 0
	for i=1,6 do
		local l = findEntity("lr_"..i)
		l.clickable:enable()
	end
end
2.3 checkRiddle(sender)
SpoilerShow

Code: Select all

function checkRiddle(sender)
	if riddleSet == 1 and check_index < 7 then
		local seq_lever = findEntity("lr_"..riddle[check_index])
		-- DEBUG print("SEQ["..check_index.."]: "..seq_lever.id.." , PRESSED: "..sender.go.id)
		if seq_lever.id == sender.go.id then
			if check_index == 6 then
				riddleEnd(1)
			else
				hudPrint(check_index.." out of 6 levers moved in correct order. Keep going")
				check_index = check_index + 1
			end
		else
			lr_trials.counter:decrement()
			lr_button.clickable:enable()
			riddleSet = 0
			disableLevers()
			if lr_trials.counter:getValue() == 0 then
				riddleEnd(0)
			else
				if riddleSet == 1 then 
					hudPrint("Wrong. Try again with new combination.")
				end
			end
		end
	else
		
	end
end
2.4 disableLevers() - well, nothing fancy, just disable the levers after the player fails until new sequence is chosen
SpoilerShow

Code: Select all

function disableLevers()
	for i=1,6 do
		local l = findEntity("lr_"..i)
		l.clickable:disable()
		if l.lever:isActivated() then
			l.lever:toggle()
		end
	end
end
2.5 riddleEnd(status) - just a finishing function to finally block the levers and button either if: player completes the riddle OR players fails to complete the riddle for 3 times
SpoilerShow

Code: Select all

function riddleEnd(status)
	if status == 1 then
		lr_button.clickable:disable()
		disableLevers()
		hudPrint("Combination entered succesfully. Congratulations.")
		lr_wt.walltext:setWallText("Combination entered succesfully.")
		riddleSet = 0
		-- PUT YOUR REWARD HERE
	else
		lr_button.clickable:disable()
		hudPrint("That was your last attempt. Sorry.")
		lr_wt.walltext:setWallText(lr_trials.counter:getValue().." attempt(s) left")
	end
end
IV. Connections (hooks):
SpoilerShow
1. lr_1 lr_2 lr_3 lr_4 lr_5 lr_6 :onToggle - lr_script:checkRiddle()
2. lr_button:onActivate - lr_script:resetRiddle()
3. lr_button:onActivate - lr_timer:start
4. lr_timer:onActivate - lr_script:createRiddle()
V. Ideas - things I thought about but didn't put them actually in
SpoilerShow
1. Adding bossfight entity to show progress if the correct lever is moved by the player
2. Number of lever movements and max attempts are fixed - 6 and 3. They could be dependant on counters for easier configuration.
3. After unsuccessfull attempt player is punished just by subst. 1 attempt from the total 3. Spawner with fireball could be added in example :)
VI. Whole contents of script_entity lr_script:
SpoilerShow

Code: Select all

lr_1:setWorldPosition(26.9999,-0.49,29.5,0)
lr_2:setWorldPosition(26.9999,-0.49,29.1,0)
lr_3:setWorldPosition(26.9999,-0.49,28.7,0)
lr_4:setWorldPosition(26.9999,-0.49,28.3,0)
lr_5:setWorldPosition(26.9999,-0.49,27.9,0)
lr_6:setWorldPosition(26.9999,-0.49,27.5,0)
lr_button:setWorldPositionY(0.6)

riddleSet = 0


function createRiddle()
	lr_button.clickable:disable()
	if riddle_index < 7 then
		riddle[riddle_index] = math.random(6)
		local lever = findEntity("lr_"..riddle[riddle_index])
		lever.lever:toggle()
	else
		if riddle_index > 9 then
			for i=1,6 do
				local l = findEntity("lr_"..i)
				if l.lever:isActivated() then
					l.lever:toggle()
				end
			end
			hudPrint("Please enter correct combination to proceed. "..lr_trials.counter:getValue().." attempt(s) left")
			lr_wt.walltext:setWallText(lr_trials.counter:getValue().." attempt(s) left")
			--print("COMB: "..riddle[1]..", "..riddle[2]..", "..riddle[3]..", "..riddle[4]..", "..riddle[5]..", "..riddle[6]..".")
			lr_timer.timer:stop()
			lr_button.clickable:disable()
			riddleSet = 1
		end
	end
	riddle_index = riddle_index + 1
end

function resetRiddle()
	riddle = {}
	riddle_index = 1
	check_index = 1
	riddleSet = 0
	for i=1,6 do
		local l = findEntity("lr_"..i)
		l.clickable:enable()
	end
end

function checkRiddle(sender)
	if riddleSet == 1 and check_index < 7 then
		local seq_lever = findEntity("lr_"..riddle[check_index])
		print("SEQ["..check_index.."]: "..seq_lever.id.." , PRESSED: "..sender.go.id)
		if seq_lever.id == sender.go.id then
			if check_index == 6 then
				riddleEnd(1)
			else
				hudPrint(check_index.." out of 6 levers moved in correct order. Keep going")
				check_index = check_index + 1
			end
		else
			lr_trials.counter:decrement()
			lr_button.clickable:enable()
			riddleSet = 0
			disableLevers()
			if lr_trials.counter:getValue() == 0 then
				riddleEnd(0)
			else
				if riddleSet == 1 then 
					hudPrint("Wrong. Try again with new combination.")
				end
			end
		end
	else
		
	end
end

function disableLevers()
	for i=1,6 do
		local l = findEntity("lr_"..i)
		l.clickable:disable()
		if l.lever:isActivated() then
			l.lever:toggle()
		end
	end
end

function riddleEnd(status)
	if status == 1 then
		lr_button.clickable:disable()
		disableLevers()
		hudPrint("Combination entered succesfully. Congratulations.")
		lr_wt.walltext:setWallText("Combination entered succesfully.")
		riddleSet = 0
		-- PUT YOUR REWARD HERE
	else
		lr_button.clickable:disable()
		hudPrint("That was your last attempt. Sorry.")
		lr_wt.walltext:setWallText(lr_trials.counter:getValue().." attempt(s) left")
	end
end
That would be it, if you think something could be done more efficiently - please say it.

Blichew

Re: [Script/puzzle]Random lever movement that has to be repe

Posted: Sun Nov 02, 2014 1:18 am
by Doridion
Sticked in the superthread ! Thanks for it memory game :D

Re: [Script/puzzle]Random lever movement that has to be repe

Posted: Tue Nov 04, 2014 10:51 pm
by Lark
Hey! This is really nice. And I know just where to put it! Thank you Blichew! -Lark

Re: [Script/puzzle]Random lever movement that has to be repe

Posted: Tue Nov 04, 2014 11:58 pm
by Blichew
Lark wrote:Hey! This is really nice. And I know just where to put it! Thank you Blichew! -Lark
:D with your script..... repeat a combinatin for 64 levers. Uh - Oh.....