let me start off by saying this is just my second day ever scripting something, so bear with me. I'm trying to open a door using levers being pulled in a specific order. Now I managed to pull it off this way.
-- Sequence Lock Puzzle
function leverCheck()
if p_sequencelock_lever_1:getLeverState() == "activated" then
if p_sequencelock_lever_2:getLeverState() == "activated" then
if p_sequencelock_lever_3:getLeverState() == "activated" then
if p_sequencelock_lever_4:getLeverState() == "activated" then
p_sequencelock_door:open()
end
elseif p_sequencelock_lever_4:getLeverState() == "activated" then
p_sequencelock_lever_1:toggle()
p_sequencelock_lever_2:toggle()
p_sequencelock_lever_4:toggle()
end
elseif p_sequencelock_lever_3:getLeverState() == "activated" then
p_sequencelock_lever_1:toggle()
p_sequencelock_lever_3:toggle()
elseif p_sequencelock_lever_4:getLeverState() == "activated" then
p_sequencelock_lever_1:toggle()
p_sequencelock_lever_4:toggle()
end
elseif p_sequencelock_lever_2:getLeverState() == "activated" then
p_sequencelock_lever_2:toggle()
elseif p_sequencelock_lever_3:getLeverState() == "activated" then
p_sequencelock_lever_3:toggle()
elseif p_sequencelock_lever_4:getLeverState() == "activated" then
p_sequencelock_lever_4:toggle()
end
if p_sequencelock_lever_1:getLeverState() == "deactivated" or
p_sequencelock_lever_2:getLeverState() == "deactivated" or
p_sequencelock_lever_3:getLeverState() == "deactivated" or
p_sequencelock_lever_4:getLeverState() == "deactivated" then
p_sequencelock_door:close()
end
end
The only reason this works, is because I am not allowing wrong levers to stay activated. This makes the puzzle incredibly easy however. How can I get this to work without stopping the user from pulling the wrong levers?
Last edited by Green Cube on Thu Sep 20, 2012 1:33 am, edited 1 time in total.
I want the levers to be activated and deactivated like any other lever. But if I activate them in a specific order, in my code it's just 1,2,3,4, the door is supposed to open. If the levers are being pulled in any other order, then nothing is supposed to happen.
For now in my code it works like this:
Lever 1 -> lever 2 -> lever 4 and all levers become deactivated again. This happens with all possible orders. The only one that works is lever 1 -> lever 2 -> lever 3 -> lever 4. If I just remove the parts where the levers are being deactivated again, the script doesn't care in which order the levers were being pulled. So 3,4,2,1 for example works too.
function pullFirst()
if counterPuzzle:getValue() == 4 then
counterPuzzle:decrement()
else
resetAll()
end
end
function pullSecond()
if counterPuzzle:getValue() == 3 then
counterPuzzle:decrement()
else
resetAll()
end
end
function pullThird()
if counterPuzzle:getValue() == 2 then
counterPuzzle:decrement()
else
resetAll()
end
end
function pullFourth()
if counterPuzzle:getValue() == 1 then
counterPuzzle:decrement()
else
resetAll()
end
end
function resetAll()
counterPuzzle:reset()
lever_1:setLeverState("deactivated")
lever_2:setLeverState("deactivated")
lever_3:setLeverState("deactivated")
lever_4:setLeverState("deactivated")
end
link lever_1 to pullFirst, lever_2 to pullSecond etc
and job done - this can be as many or few levers as you like - just change the intial value of the counter to match the number of levers, and add a code slice for each new lever, counting down as you go
Last edited by Shroom on Tue Sep 18, 2012 1:02 am, edited 2 times in total.
Edit: The code is now fixed, and works with the new patch as well (no upvalues)
Main features:
Easy to add new levers, just add it to the order.
Easy to change the order of activation.
It resets all the levers to deactivated once you have tried as many times as the sequence is long
Edit: Shroom's way is also fine, but more hassle to adjust to different situations and to change the order then my version, while his is easier to understand.
-- Create a "static" variable to track the current step, start at 1 as lua tables starts at index 1
static_step = 1
static_failed = false
-- Create a timer to handle the deactivation
timer = spawn("timer", 1, 6,20,2, "timer"..self.id)
timer:setTimerInterval(0.5)
timer:addConnector("activate", self.id, "reset")
order = { lever_2, lever_3, lever_4, lever_5 }
function checkLevers()
-- Check if this step failed
if( order[static_step]:getLeverState() == "deactivated" ) then
-- Set progress to failed
static_failed = true
end
-- Wait until a full sequence have gone, then report if it was the wrong one or not
if( static_step == #order ) then
-- If the lever check failed, reset it
if( static_failed == true ) then
timer:activate()
-- Reset the steps, we set it to 0 because we increase it at the end of this function
static_step = 0
else
-- All checks passes successful, open the door
door:open()
end
end
-- Step ahead
static_step = static_step + 1
end
function reset()
for id, lever in ipairs(order) do
lever:setLeverState("deactivated")
end
static_failed = false
timer:deactivate()
end
Last edited by Lilltiger on Tue Sep 18, 2012 5:34 pm, edited 3 times in total.
I have the smallest code of em all. Or well, maybe not anymore.
Create a counter next to the lua script entity and set it to the number of inputs you want the player to make. The levers need to be named in the same pattern e.g. sequenceLock_1 to sequenceLock_4.
Lets name the counter you just placed myCustomSequenceCounter. On activation of myCustomSequenceCounter, tell the door to open. Also add an additional connector to itself to tell the counter to reset when activated.
Then connect each lever to the following lua script entity action on the "any" event:
function sequenceRiddle()
-- change the following to what entity type you want to use for your riddle
local triggerEntity = "lever"
-- all entity IDs of your activation entities should start with the below, followed by a number
local namingPattern = "sequenceLock_"
-- define the sequence in which you want your entities to be activated
local sequenceOfThings = {"1","2","4","2","3"}
-- define the ID of your sequenceCounter
-- important: this sequence counter needs to have the same initial value
-- as the number of sequences you defined above
local sequenceCounterID = "myCustomSequenceCounter"
-- from here on, it shouldn't be needed to alter the rest of the code
local curSeq = #sequenceOfThings+1-findEntity(sequenceCounterID):getValue()
for i in entitiesAt(party.level, party.x, party.y) do
if i.name == triggerEntity then
if i.id == namingPattern..sequenceOfThings[curSeq] then
findEntity(sequenceCounterID):decrement()
else
findEntity(sequenceCounterID):reset()
end
end
end
end
The only "downside" is, that there mustn't be multiple levers or activation entities in one square (like one on each side of the square) or else the code will not work.
Last edited by Montis on Tue Oct 23, 2012 10:58 am, edited 5 times in total.
Nice to see all these alternatives, it really helps to learn how some moderately advanced scripting works. And these would make great additions to the Useful Scripts Repository! viewtopic.php?f=14&t=3099&start=30
Lilltiger wrote:Here is some code that might help, it's untested, but it should work, although might be some typos.
Main features:
Easy to add new levers, just add it to the order.
Easy to change the order of activation.
It resets all the levers to deactivated once you have tried as many times as the sequence is long
Main Disadvantages:
The code is untested
Edit: Shroom's way is also fine, but more hassle to adjust to different situations and to change the order then my version, while his is easier to understand.
My code is very basic - I am learning lua and it does show how with no specific language knowledge you can do a lot - but using arrays/tables as shown is much more powerful - I took a minute to have a look (and suggest you do if your into it http://www.lua.org/pil/) and this is really a very simple language if you already use java or c/c#. I think the main thing I took from this is the use of tables - very powerful (http://www.lua.org/pil/2.5.html)
Montis's code is also very good - it shows how objects can be manipulated by concatenation of strings