Page 1 of 3

Lever Puzzle Scripting Help

Posted: Wed Jan 02, 2013 9:59 pm
by Babby Tutel
Hey guys.

New to both modding and Lua, but I'm trying to make a sort of "test map" for myself, without using many custom assets and trying to use some simplistic scripts. I want to have a lever puzzle where you must turn a set of five levers from "deactivated" to "activated", but when you activate one lever it inverts the two beside it (or one, in the case of the two end-levers). I don't really have a full grasp of Lua yet, so I'm wondering how to go about that.

Thanks in advance.

Re: Lever Puzzle Scripting Help

Posted: Wed Jan 02, 2013 11:52 pm
by aaneton
Something like this:

1) create 5 levers named ID lever1, lever2 etc...
2) create a door (id: eg_door) or whatever you want to open/change when all levers are correct
2) create script_entity (id: test_script) with following code.

Code: Select all

function Lever1Pull()
 lever2:toggle()   
end
function Lever2Pull()
 lever1:toggle()
 lever3:toggle()
end
function Lever3Pull()
 lever2:toggle()
 lever4:toggle()
end
function Lever4Pull()
 lever3:toggle()
 lever5:toggle()
end
function Lever5Pull()
 lever4:toggle()
end

function CheckLeverStates()
 if lever1:getLeverState() == "activated" and lever2:getLeverState() == "activated" and lever3:getLeverState() == "activated" and lever4:getLeverState() == "activated" and lever5:getLeverState() == "activated" then
 eg_door:open()
 end
end
3) connect lever (1) to script

add connector to lever
Event: any
Target: test_script
Action: Lever1Pull

add second connector to lever
Event: any
Target: test_script (ID of your script entity)
Action: CheckLeverStates

(do this for all 5 levers with Action matching lever number.)

I have not tested the code, I wrote this answer here directly so it might not work 100%. Hopefully you get the idea, you need to change state of levers next to the pulled one and check all lever states at every pull. There are more elegant (and bug free?)ways to do this as this might not work if states are change after check. You could e.g. combine everything into one function (both toggle and check), then you would just need one connector for each lever. Please go to http://www.grimrock.net/modding/how-to- ... tion-lock/ and http://www.grimrock.net/modding/scripting-reference/ for more help

Re: Lever Puzzle Scripting Help

Posted: Wed Jan 02, 2013 11:57 pm
by Komag
each of those functions will only need one end, not two. and you can connect them all to their respective scripts with one any instead of both an activate and a deactivate

Re: Lever Puzzle Scripting Help

Posted: Thu Jan 03, 2013 12:01 am
by aaneton
Fixed as Komag noted (double end was copy paste mistake and forgot about any :) )

Re: Lever Puzzle Scripting Help

Posted: Thu Jan 03, 2013 4:23 am
by Babby Tutel
Thanks for the replies, guys. I was going about the script completely wrong. I'll post later if there are any problems.

Re: Lever Puzzle Scripting Help

Posted: Thu Jan 03, 2013 5:00 am
by Babby Tutel
I get a stack overflow at the second line of code (lever2:toggle()) no matter which lever I touch. I was originally giving each lever it's own unique script, could that be a preventative?

Hitting the bricks, will check in the morning for replies. Any help is appreciated.

Re: Lever Puzzle Scripting Help

Posted: Thu Jan 03, 2013 5:43 am
by Komag
Hmm, I think it's forever doing a huge loop! When you toggle a lever it pretends you actually threw the lever, so it will run that function, which toggles lever 1, which toggles lever 2, etc etc etc forever to infinity!!!

You might have to code in some circuit breakers, such as timers that cause the surrounding levers not to toggle their scripts but to just to up and down, or else you may need to code the whole thing differently (but I think the breakers may be necessary). Could have flags set by timers, so that when you pull lever 1 it sets the flag lever1Pulled to true, but also starts a timer lasting 0.2s which then triggers another function setting all the flags back to false. Meanwhile, the functions will only trigger surrounding levers to toggle() so long as their flags are false (or something like that - but it might still cascade down the line, hmm, would take some testing and thinking through...)

Re: Lever Puzzle Scripting Help

Posted: Thu Jan 03, 2013 5:56 am
by Babby Tutel
Couldn't sleep so I checked the thread. Should I add in 'break', or does that halt the entire script?

Also, same question, would giving each lever it's own script take the load off, as I could simply break the loop for the involved levers for each script rather than code timers for each toggle in the main script?

Re: Lever Puzzle Scripting Help

Posted: Thu Jan 03, 2013 1:32 pm
by Grimwold
This is a tricky one... as a lever:toggle() will always trigger the script it is connected to.

I think one option is to use some sort of "flag" system to regulate which levers are allowed to toggle.. combined with a hidden pressure plate in front of each lever to alter the appropriate flags.

So for example plate_3 will set flag_3 = 1 and will set all other flags = 0

then if lever_3 is toggled it will first check to see that flag_3 = 1 and if so, it will set flag_3 = 0 and call for toggles of each of lever_2 and lever_4

each lever toggle will check for it's appropriate flag before calling for other levers to be toggled.


The script would be something like this -

Code: Select all

flag_1 = 0
flag_2 = 0
flag_3 = 0
flag_4 = 0
flag_5 = 0

function plate1Trigger()
  if plate_1:isDown() then
    flag_1 = 1
    flag_2 = 0
    flag_3 = 0
    flag_4 = 0
    flag_5 = 0
  end
end

function plate2Trigger()
  if plate_2:isDown() then
    flag_1 = 0
    flag_2 = 1
    flag_3 = 0
    flag_4 = 0
    flag_5 = 0
  end
end

function plate3Trigger()
  if plate_3:isDown() then
    flag_1 = 0
    flag_2 = 0
    flag_3 = 1
    flag_4 = 0
    flag_5 = 0
  end
end

function plate4Trigger()
  if plate_4:isDown() then
    flag_1 = 0
    flag_2 = 0
    flag_3 = 0
    flag_4 = 1
    flag_5 = 0
  end
end

function plate5Trigger()
  if plate_5:isDown() then
    flag_1 = 0
    flag_2 = 0
    flag_3 = 0
    flag_4 = 0
    flag_5 = 1
  end
end

function lever1Toggle()
  if flag_1 == 1 then
    flag_1 = 0
    lever_2:toggle()
  end
end

function lever2Toggle()
  if flag_2 == 1 then
    flag_2 = 0
    lever_1:toggle()
    lever_3:toggle()
  end
end

function lever3Toggle()
  if flag_3 == 1 then
    flag_3 = 0
    lever_2:toggle()
    lever_4:toggle()
  end
end

function lever4Toggle()
  if flag_4 == 1 then
    flag_4 = 0
    lever_3:toggle()
    lever_5:toggle()
  end
end

function lever5Toggle()
  if flag_5 == 1 then
    flag_5 = 0
    lever_4:toggle()
  end
end
Connect each hidden plate to its corresponding function (triggered by party only), and connect each lever to its corresponding function also. This should work in theory, but is untested.

Re: Lever Puzzle Scripting Help

Posted: Thu Jan 03, 2013 2:24 pm
by Komag
If you use invisible plates (good idea!) then you shouldn't need flags I think:

Code: Select all

function lever1Toggle()
  if plate_1:isDown() then
    lever_2:toggle()
  end
end

function lever2Toggle()
  if plate_2:isDown() then
    lever_1:toggle()
    lever_3:toggle()
  end
end

function lever3Toggle()
  if plate_3:isDown() then
    lever_2:toggle()
    lever_4:toggle()
  end
end

function lever4Toggle()
  if plate_4:isDown then
    lever_3:toggle()
    lever_5:toggle()
  end
end

function lever5Toggle()
  if plate_5:isDown then
    lever_4:toggle()
  end
end
make sure invisible plates are set to party only