The idea is that the party has to walk over a series of pressure plates in the correct order. If they go out of sequence, they are teleported back to the start. I managed to script it to allow duplicates, so you can require the party to walk over the same square more than once in a sequence and you can also include 'fake' squares that will always reset the puzzle.
This script can be used any number of times in a dungeon by pasting it into different script entities, (provided the counter and reset_plate variables in each version are changed to unique values). Unfortunately it will not be possible to re-use plates from one puzzle in another, as the script for the 1 variation will end up teleporting you out even if you are correct for a 2nd variation.
You will need to place a door and a number of pressure plates (hidden or otherwise) in your dungeon, noting their ID values, and decide on co-ordinates for a destination for the teleport/reset. Then paste the following script into a script entity in your dungeon and edit the settings in the first few lines to customise it.
Code: Select all
counter_name = "hidden_path_counter_1"
reset_plate_name = "path_reset_1"
door_name = "hidden_path_door_1"
destination = {level=2, x=17, y=18, facing=2}
silent = 1
punish = 1
function checkPath(trigger)
local plate_check = {"pressure_plate_hidden_2","pressure_plate_hidden_3","pressure_plate_hidden_4","pressure_plate_hidden_5","pressure_plate_hidden_6","pressure_plate_hidden_7","pressure_plate_hidden_8","pressure_plate_hidden_12","pressure_plate_hidden_11","pressure_plate_hidden_10","pressure_plate_hidden_8","pressure_plate_hidden_9"}
local plate_fake = {"pressure_plate_hidden_13"}
if initialisation == 1 then
local unique_plate_check = removeDuplicates(plate_check)
local unique_plate_fake = removeDuplicates(plate_fake)
for i=1,#unique_plate_check do
local plate_entity = findEntity(unique_plate_check[i])
if plate_entity == nil then
print(unique_plate_check[i] .. " is missing")
break
else
plate_entity:setTriggeredByParty(true)
plate_entity:setTriggeredByMonster(false)
plate_entity:setTriggeredByItem(false)
plate_entity:setActivateOnce(false)
plate_entity:addConnector("activate",self.id,"checkPath")
local tele_name = plate_entity.id .. "_tele"
local tele_entity = findEntity(tele_name)
if tele_entity ~= nil then
print(tele_name .. " already exists")
else
spawn("teleporter",plate_entity.level,plate_entity.x,plate_entity.y,plate_entity.facing,tele_name)
:setTeleportTarget(destination.x,destination.y,destination.facing,destination.level)
:deactivate()
if silent == 1 then
findEntity(tele_name):setInvisible(true):setHideLight(true):setSilent(true):setScreenFlash(false)
end
end
end
end
for i=1,#unique_plate_fake do
local fake_entity = findEntity(unique_plate_fake[i])
if fake_entity == nil then
print(unique_plate_fake[i] .. " is missing")
break
else
fake_entity:setTriggeredByParty(true)
fake_entity:setTriggeredByMonster(false)
fake_entity:setTriggeredByItem(false)
fake_entity:setActivateOnce(false)
fake_entity:addConnector("activate",self.id,"checkPath")
local tele_name = fake_entity.id .. "_tele"
local tele_entity = findEntity(tele_name)
if tele_entity ~= nil then
print(tele_name .. " already exists")
else
spawn("teleporter",fake_entity.level,fake_entity.x,fake_entity.y,fake_entity.facing,tele_name)
:setTeleportTarget(destination.x,destination.y,destination.facing,destination.level)
:deactivate()
if silent == 1 then
findEntity(tele_name):setInvisible(true):setHideLight(true):setSilent(true):setScreenFlash(false)
end
end
end
end
if findEntity(reset_plate_name) ~= nil then
print(reset_plate_name .. " already exists in dungeon")
else
spawn("pressure_plate_hidden",destination.level,destination.x,destination.y,destination.facing,reset_plate_name)
:setTriggeredByParty(true)
:setTriggeredByMonster(false)
:setTriggeredByItem(false)
:setActivateOnce(false)
:addConnector("activate",self.id,"destroyTele")
end
end
local range = #plate_check
local counter_entity = findEntity(counter_name)
local door_entity = findEntity(door_name)
if counter_entity == nil then
spawn("counter",self.level,self.x,self.y,self.facing,counter_name)
:setInitialValue(range)
:setValue(range)
:addConnector("activate",door_entity.id,"open")
:addConnector("deactivate",door_entity.id,"close")
end
local counter_entity = findEntity(counter_name)
local plate_index = range + 1 - counter_entity:getValue()
if trigger ~= nil then
if trigger.id == plate_check[plate_index] then
counter_entity:decrement()
else
counter_entity:reset()
if punish == 1 then
spawn("poison_cloud",destination.level,destination.x,destination.y,destination.facing)
end
activated_tele = trigger.id .. "_tele"
local tele_entity = findEntity(activated_tele)
if tele_entity ~= nil then
tele_entity:activate()
else
print(activated_tele .. " is missing. Internal script error")
end
-- spawn("teleporter",party.level,party.x,party.y,party.facing,"temp_teleport")
-- :setTeleportTarget(destination.x,destination.y,destination.facing,destination.level)
end
end
if initialisation == 1 then
initialisation = 0
end
end
function destroyTele()
local tele_entity = findEntity(activated_tele)
if tele_entity ~= nil then
tele_entity:deactivate()
end
end
function isInTable(table, element)
for _,value in pairs(table) do
if value == element then
return true
end
end
return false
end
function removeDuplicates(t)
local t2 = {}
local idx = 1
for k,v in pairs(t) do
if not isInTable(t2,v) then
t2[idx] = v
idx = idx+1
end
end
return t2
end
initialisation = 1
activated_tele = ""
checkPath()
These are the settings you will need to customise from the first few lines of the script:
counter_name = "hidden_path_counter_1"
replace the text hidden_path_counter_1 with a unique name for a counter. You do not need to place the counter in the dungeon, but you need to make sure that this ID is not used for anything else in your dungeon (and does not duplicate the ID of a counter in a subsequent copy of this script)
reset_plate_name = "path_reset_1"
replace the text path_reset_1 with a unique name for a hidden pressure plate. You do not need to place the plate in the dungeon, but you need to make sure that this ID is not used for anything else in your dungeon (and does not duplicate the ID of a plate in a subsequent copy of this script)
door_name = "hidden_path_door_1"
replace the text hidden_path_door_1 with the ID of the door you want to open with this puzzle. You must place this door somewhere in your dungeon.
destination = {level=3, x=17, y=18, facing=2}
replace the numerical values in this list with the co-ordinates of the destination/reset square. Ideally this will be at the entrance to your puzzle.
silent = 1
if set to 1, then the teleporters will activate silently and with no visual effects.. this could be handy for disguising the fact that the party has been teleported.. a bit like the medusa room puzzle in the Original. If you want the bells and whistles, set this to 0
punish = 1
if set to 1, then a poison cloud will be spawned at the reset destination to "punish" the party for an incorrect attempt. If you are a more lenient dungeon master and do not wish to punish the party, set this value to 0
local plate_check = {"pressure_plate_hidden_2","pressure_plate_hidden_3","pressure_plate_hidden_4","pressure_plate_hidden_5","pressure_plate_hidden_6","pressure_plate_hidden_7","pressure_plate_hidden_8","pressure_plate_hidden_12","pressure_plate_hidden_11","pressure_plate_hidden_10","pressure_plate_hidden_8","pressure_plate_hidden_9"}
replace the entries in this list with the IDs of the plates that map out the path you wish the party to take. You can add as many entries here as you want and can include duplicates. If you are placing plates next to each other in room you must be aware that the party can only move in the 4 orthogonal directions (i.e. not diagonal) so plan your list of plates accordingly.
local plate_fake = {"pressure_plate_hidden_13"}
replace the entries in this list with the IDs of the fake plates... these are the ones over which the party should never travel to solve the puzzle. They will automatically reset the puzzle. You can put as many entries as you like in this list (separating each entry with a comma), duplicates are allowed but will be ignored.