Page 2 of 3
Re: How to make pit puzzle, such as the chamber of pits?
Posted: Thu Sep 27, 2012 5:12 am
by Komag
so I'm testing antti's version, just for kicks, and got a very weird crash
my script so far:
Code: Select all
time = 1
function pitSequence()
local sequence = { pitpuz7, pitpuz4, pitpuz1, pitpuz2, pitpuz3, pitpuz6, pitpuz5, pitpuz8, pitpuz9 } --this doesn't contain ALL the pits, only the exact sequence or the path of closing and opening pits
sequence[time]:close() --close a pit in the sequence
-- sequence[time-3]:open() --and then open a pit again a few steps behind
time = time + 1
end
I just wanted to see it close them in my order - I have 9 pits:
1 2 3
4 5 6
7 8 9 z
x
so I have them closing 7 4 1, 2 3, 6 5, 8 9, so I can move from x to z
Anyway, without any method yet to shut down the timer, soon after 9 closed, I got a crash, and my mouse was stuck to the middle of the screen, even if I alt=tabbed to other windows open! I had to use keyboard shortcuts to close the editor, then my mouse was free again!
But I feel a little sense of déjà vu - is this already a known bug, that when using mouselook and you get a crash then the mouse is stuck near the screen center? I didn't see it on the "known issues" list for 1.2.11.
The error is:
sequence[time]:close() --close a pit in the sequence - "attempt to index a nil value" and it's right when the next timer tick happens after closing the last pit
Re: How to make pit puzzle, such as the chamber of pits?
Posted: Thu Sep 27, 2012 5:40 am
by Komag
I'm almost there!!! but I have to go to bed, and I'll be busy most of the day tomorrow. Here's what I've got so far, working partially:
Code: Select all
time = 1
function pitSequence()
local sequence = { pitpuz7, pitpuz4, pitpuz1, pitpuz2, pitpuz3, pitpuz6, pitpuz5, pitpuz8, pitpuz9 }
if time < 10 then
sequence[time]:close() --close a pit in the sequence
end
if time > 2 then
sequence[time-2]:open() --and then open a pit again a few steps behind
end
if levercount == 2 then
time = time + 1
else
time = time - 1
end
if time == 12 then
time = 1
pitpuztimer:deactivate()
end
end
levercount = 2
function leverPull()
if pitpuzlever1:getLeverState() == activated and
pitpuzlever2:getLeverState() == activated then
levercount = 2
time = 1
elseif pitpuzlever1:getLeverState() == deactivated and
pitpuzlever2:getLeverState() == deactivated then
levercount = 2
time = 1
else
levercount = 1
time = 11
end
end
The two levers are located on either end of the pit puzzle (like in the original game), along with a button on each end, and the levers are linked to the script with the leverpull function (the buttons are linked to a 1sec timer linked to the script with the pitSequence function).
I haven't yet set up the levers to cancel and open all the pits if they're in the middle of the sequence.
The forward sequence works well. The reverse sequence works partially, but I only barely rigged it so I haven't set up proper pit closing or stopping it at the right time, so it will crash with an attempt to index a nil value.
Re: How to make pit puzzle, such as the chamber of pits?
Posted: Thu Sep 27, 2012 1:19 pm
by Komag
Okay, this works perfectly so far as I have tested, including pulling the lever halfway through to reset everything:
Code: Select all
time = 1
function pitSequence()
local sequence = { pitpuz7, pitpuz4, pitpuz1, pitpuz2, pitpuz3, pitpuz6, pitpuz5, pitpuz8, pitpuz9 } -- doesn't have to include all pits, just the path you want
if levercount == 2 then
if time < 10 then
sequence[time]:close() --close a pit in the sequence
end
if time > 2 then
sequence[time-2]:open() --and then open a pit again two steps behind
end
time = time + 1
if time == 12 then
time = 1
pitpuztimer:deactivate()
end
elseif levercount == 1 then
if time > 2 then
sequence[time-2]:close() --close a pit in the sequence
end
if time < 10 then
sequence[time]:open() --and then open a pit again two steps behind
end
time = time - 1
if time == 0 then
time = 11
pitpuztimer:deactivate()
end
end
end
levercount = 2
function leverPull()
if pitpuzlever1:getLeverState() == "activated" and
pitpuzlever2:getLeverState() == "activated" then
levercount = 2
time = 1
elseif pitpuzlever1:getLeverState() == "deactivated" and
pitpuzlever2:getLeverState() == "deactivated" then
levercount = 2
time = 1
else
levercount = 1
time = 11
end
for i=1,9 do
local pit = findEntity("pitpuz"..i)
if pit then
pit:open()
end
end
pitpuztimer:deactivate()
end
- link the two buttons to the timer, which is linked to the script with pitSequence
- link the two levers to the script directly with leverPull
Re: How to make pit puzzle, such as the chamber of pits?
Posted: Thu Sep 27, 2012 1:51 pm
by Komag
another version, with much easier customization (with notes where to do it) for you:
Code: Select all
time = 1
steps = 9 -- CUSTOMIZE: HOW MANY STEPS YOU HAVE
thetimer = pitpuztimer -- CUSTOMIZE: ID OF THE TIMER
function pitSequence()
local sequence = { pitpuz7, pitpuz4, pitpuz1, pitpuz2, pitpuz3, pitpuz6, pitpuz5, pitpuz8, pitpuz9 } -- CUSTOMIZE: IDS OF THE PITS YOU WANT TO CLOSE, IN ORDER
if levercount == 2 then
if time < steps + 1 then
sequence[time]:close() --close a pit in the sequence
end
if time > 2 then
sequence[time-2]:open() --and then open a pit again two steps behind
end
time = time + 1
if time == steps + 3 then
time = 1
thetimer:deactivate()
end
elseif levercount == 1 then
if time > 2 then
sequence[time-2]:close() --close a pit in the sequence
end
if time < steps + 1 then
sequence[time]:open() --and then open a pit again two steps behind
end
time = time - 1
if time == 0 then
time = steps + 2
thetimer:deactivate()
end
end
end
levercount = 2
function leverPull()
if pitpuzlever1:getLeverState() == "activated" and -- CUSTOMIZE: ID OF LEVER1
pitpuzlever2:getLeverState() == "activated" then -- CUSTOMIZE: ID OF LEVER2
levercount = 2
time = 1
elseif pitpuzlever1:getLeverState() == "deactivated" and -- CUSTOMIZE: ID OF LEVER1
pitpuzlever2:getLeverState() == "deactivated" then -- CUSTOMIZE: ID OF LEVER2
levercount = 2
time = 1
else
levercount = 1
time = steps + 2
end
for i=1,steps do
local pit = findEntity("pitpuz"..i) -- CUSTOMIZE: PARTIAL ID OF PITS
if pit then
pit:open()
end
end
thetimer:deactivate()
end
Re: How to make pit puzzle, such as the chamber of pits?
Posted: Thu Sep 27, 2012 2:51 pm
by antti
Komag wrote:another version, with much easier customization (with notes where to do it) for you:
Code: Select all
time = 1
steps = 9 -- CUSTOMIZE: HOW MANY STEPS YOU HAVE
thetimer = pitpuztimer -- CUSTOMIZE: ID OF THE TIMER
function pitSequence()
local sequence = { pitpuz7, pitpuz4, pitpuz1, pitpuz2, pitpuz3, pitpuz6, pitpuz5, pitpuz8, pitpuz9 } -- CUSTOMIZE: IDS OF THE PITS YOU WANT TO CLOSE, IN ORDER
if levercount == 2 then
if time < steps + 1 then
sequence[time]:close() --close a pit in the sequence
end
if time > 2 then
sequence[time-2]:open() --and then open a pit again two steps behind
end
time = time + 1
if time == steps + 3 then
time = 1
thetimer:deactivate()
end
elseif levercount == 1 then
if time > 2 then
sequence[time-2]:close() --close a pit in the sequence
end
if time < steps + 1 then
sequence[time]:open() --and then open a pit again two steps behind
end
time = time - 1
if time == 0 then
time = steps + 2
thetimer:deactivate()
end
end
end
levercount = 2
function leverPull()
if pitpuzlever1:getLeverState() == "activated" and -- CUSTOMIZE: ID OF LEVER1
pitpuzlever2:getLeverState() == "activated" then -- CUSTOMIZE: ID OF LEVER2
levercount = 2
time = 1
elseif pitpuzlever1:getLeverState() == "deactivated" and -- CUSTOMIZE: ID OF LEVER1
pitpuzlever2:getLeverState() == "deactivated" then -- CUSTOMIZE: ID OF LEVER2
levercount = 2
time = 1
else
levercount = 1
time = steps + 2
end
for i=1,steps do
local pit = findEntity("pitpuz"..i) -- CUSTOMIZE: PARTIAL ID OF PITS
if pit then
pit:open()
end
end
thetimer:deactivate()
end
I don't think you need the steps variable if it is there to just indicate how many pits you have in the sequence table. You could just replace them with #sequence, which gets the length of the table. It would simplify the customization a little bit as well.
Re: How to make pit puzzle, such as the chamber of pits?
Posted: Thu Sep 27, 2012 3:14 pm
by Komag
Ah, thanks, I was wondering if there was a way to get that, didn't know about the #. I'm at the courthouse on jury duty right now, but I'll update this tonight
Re: How to make pit puzzle, such as the chamber of pits?
Posted: Thu Sep 27, 2012 11:50 pm
by Komag
antti wrote:I don't think you need the steps variable if it is there to just indicate how many pits you have in the sequence table. You could just replace them with #sequence, which gets the length of the table. It would simplify the customization a little bit as well.
hmm, tried it, but it's used in the separate leverPull function, so it crashes with "attempt to get length of global 'sequence' (a nil value)
it works correctly if I just pull out the sequence and put it at the top to make it global, but is there any reason to avoid doing that?
Re: How to make pit puzzle, such as the chamber of pits?
Posted: Fri Sep 28, 2012 1:27 am
by Montis
I would say no, since no variables are really global.
Re: How to make pit puzzle, such as the chamber of pits?
Posted: Fri Sep 28, 2012 2:11 am
by Komag
here is the altered version with streamlined CUSTOMIZATION all at the top:
Code: Select all
thetimer = pitpuztimer -- CUSTOMIZE: ID OF THE TIMER
thelever1 = pitpuzlever1 -- CUSTOMIZE: ID OF THE FIRST LEVER
thelever2 = pitpuzlever2 -- CUSTOMIZE: ID OF THE SECOND LEVER
namepart = "pitpuz" -- CUSTOMIZE: PARTIAL ID OF PITS
sequence = { pitpuz7, pitpuz4, pitpuz1, pitpuz2, pitpuz3, pitpuz6, pitpuz5, pitpuz8, pitpuz9 } -- CUSTOMIZE: IDS OF THE PITS YOU WANT TO CLOSE, IN ORDER
time = 1
function pitSequence()
if levercount == 2 then
if time < #sequence + 1 then
sequence[time]:deactivate() --close a pit in the sequence
end
if time > 2 then
sequence[time-2]:activate() --and then open a pit again two steps behind
end
time = time + 1
if time == #sequence + 3 then
time = 1
thetimer:deactivate()
end
elseif levercount == 1 then
if time > 2 then
sequence[time-2]:deactivate() --close a pit in the sequence
end
if time < #sequence + 1 then
sequence[time]:activate() --and then open a pit again two steps behind
end
time = time - 1
if time == 0 then
time = #sequence + 2
thetimer:deactivate()
end
end
end
levercount = 2
function leverPull()
if thelever1:getLeverState() == "activated" and
thelever2:getLeverState() == "activated" then
levercount = 2
time = 1
elseif thelever1:getLeverState() == "deactivated" and
thelever2:getLeverState() == "deactivated" then
levercount = 2
time = 1
else
levercount = 1
time = #sequence + 2
end
for i=1,#sequence do
local pit = findEntity(namepart..i)
if pit then
pit:activate()
end
end
thetimer:deactivate()
end
tested and working well, nice and clean to implement

Re: How to make pit puzzle, such as the chamber of pits?
Posted: Fri Sep 28, 2012 5:26 am
by Komag
the dungeon crashed when trying to load into the real game as a custom dungeon:
pitpuzscript: cannot serialize table 'thetimer' with metatable
stack traceback:
[C]: in function 'error'
[string "ScriptEntity.lua"]: in function 'saveValue'
[string "ScriptEntity.lua"]: in function 'saveState'
[string "GameMode.lua"]: in function 'saveGame'
[string "GameMode.lua"]: in function 'autoSave'
[string "GameMode.lua"]: in function 'newGame'
[string "GameMode.lua"]: in function 'startGame'
[string "NewGameMenu.lua"]: in function 'startGame'
[string "NewGameMenu.lua"]: in function 'update'
[string "GameMode.lua"]: in function 'update'
[string "Grimrock.lua"]: in function 'display'
[string "Grimrock.lua"]: in main chunk