[Script] Generic Alcove Item Puzzle

Talk about creating Grimrock 1 levels and mods here. Warning: forum contains spoilers!
Post Reply
User avatar
Grimwold
Posts: 511
Joined: Thu Sep 13, 2012 11:45 pm
Location: A Dungeon somewhere in the UK

[Script] Generic Alcove Item Puzzle

Post by Grimwold »

The alcove item puzzle is one that many of us like to use in our dungeons and we get a lot of requests here for help with scripting it, so I have cooked up this generic script that can be added to any dungeon, as many times as necessary.
It can very easily be customised for any number of alcoves(altars) requiring an item on each.

Firstly you need to add alcoves to your dungeon and give them appropriate IDs. Decide what items need to be in each. Add a door that is to be opened when everything is set and give that a suitable ID also.

Next paste this script into a script_entity in your dungeon.

Code: Select all

counter_name = "alcove_counter_1"
door_name = "armordoor"

function newItemCheck()
  local item_check = {
    alcoves = {"altar_1","altar_2","altar_3","altar_4"}, 
    items = {"chitin_boots", "chitin_greaves", "chitin_mail", "chitin_mask"}}
  if initialisation == 1 then
    for i=1,#item_check["alcoves"] do
      local alcove_entity = findEntity(item_check["alcoves"][i])
      if alcove_entity == nil then
        print(item_check["alcoves"][i] .. " is missing")
        break
      else
        alcove_entity:setActivateAlways(true)
        alcove_entity:addConnector("any",self.id,"newItemCheck")
      end
    end
  end
  local range = math.min(#item_check["alcoves"],#item_check["items"])
  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)
  for i = 1,range do
    local alcove_entity = findEntity(item_check["alcoves"][i])
    if alcove_entity ~= nil and containsItem(alcove_entity, item_check["items"][i]) then
      counter_entity:decrement()
    end
  end
-- if we get to here and the counter is not 0 we reset the counter
  if counter_entity:getValue() ~= 0 then
    counter_entity:reset()
  end
  if initialisation == 1 then
    initialisation = 0
  end
end

-- This function returns true if the entity contains a given item.
-- It works for any entity that implements the containedItems() method.
function containsItem(entity, item)
  for i in entity:containedItems() do
    if i.name == item then
      return true
    end
  end
-- if we get here the item was not found
  return false
end

initialisation = 1

newItemCheck()
Finally you will need to customise the following entries in the first few lines of the script:
counter_name = "alcove_counter_1"
replace the text alcove_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)

door_name = "armordoor"
replace the text armordoor with the ID of the door you want to open with this puzzle. You must place this door somewhere in your dungeon.

alcoves = {"altar_1","altar_2","altar_3","altar_4"},
replace the entries in this list with the IDs of the alcoves(or altars) that you placed in your dungeon. You can add as many entries here as you want. If you want to have fewer items than alcoves, list the ones that need an object first, and any empty ones afterwards

items = {"chitin_boots", "chitin_greaves", "chitin_mail", "chitin_mask"}}
replace the entries in this list with the names of the items you require to placed in the alcoves. they should be in the same order as the alcoves into which they need to be placed. So here, "chitin_boots" need to be placed on "altar_1" etc.


with that done your alcove puzzle should be good to go.


Here's another example.. 5 alcoves with 3 requiring a rock.
SpoilerShow

Code: Select all

    counter_name = "alcove_counter_2"
    door_name = "dungeon_door_metal_1"

    function newItemCheck()
      local item_check = {
        alcoves = {"dungeon_alcove_2","dungeon_alcove_4","dungeon_alcove_5","dungeon_alcove_1","dungeon_alcove_3"},
        items = {"rock", "rock", "rock"}}
      if initialisation == 1 then
        for i=1,#item_check["alcoves"] do
          local alcove_entity = findEntity(item_check["alcoves"][i])
          if alcove_entity == nil then
            print(item_check["alcoves"][i] .. " is missing")
            break
          else
            alcove_entity:setActivateAlways(true)
            alcove_entity:addConnector("any",self.id,"newItemCheck")
          end
        end
      end
      range = math.min(#item_check["alcoves"],#item_check["items"])
      local counter_entity = findEntity(counter_name)
      local door_entity = findEntity(door_name)
      if counter_entity == nil then
        spawn("counter",party.level,party.x,party.y,party.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)
      for i = 1,range do
        local alcove_entity = findEntity(item_check["alcoves"][i])
        if alcove_entity ~= nil and containsItem(alcove_entity, item_check["items"][i]) then
          counter_entity:decrement()
        end
      end
    -- if we get to here and the counter is not 0 we reset the counter
      if counter_entity:getValue() ~= 0 then
    counter_entity:reset()
  end
  if initialisation == 1 then
    initialisation = 0
  end
end

    -- This function returns true if the entity contains a given item.
    -- It works for any entity that implements the containedItems() method.
    function containsItem(entity, item)
      for i in entity:containedItems() do
        if i.name == item then
          return true
        end
      end
    -- if we get here the item was not found
      return false
    end

    initialisation = 1

    newItemCheck()
Last edited by Grimwold on Thu Dec 20, 2012 5:01 pm, edited 6 times in total.
User avatar
Komag
Posts: 3654
Joined: Sat Jul 28, 2012 4:55 pm
Location: Boston, USA

Re: [SCRIPT] Generic Alcove Item Puzzle

Post by Komag »

I've added this and the Lever combination on to the superthread, definitely worth saving! 8-)
Finished Dungeons - complete mods to play
User avatar
Grimwold
Posts: 511
Joined: Thu Sep 13, 2012 11:45 pm
Location: A Dungeon somewhere in the UK

Re: [SCRIPT] Generic Alcove Item Puzzle

Post by Grimwold »

Komag wrote:I've added this and the Lever combination on to the superthread, definitely worth saving! 8-)
Cool. Thanks Komag.
Iiyq
Posts: 2
Joined: Tue Jun 11, 2013 3:29 am

Re: [Script] Generic Alcove Item Puzzle

Post by Iiyq »

Hey, I just wanted to say thanks for this--and all the script work that goes on here. Its been an invaluable help in crafting my first dungeon.

This was just the thing I was looking for.
Post Reply