(WIP) Curious Conundrum / CFD 2012 submission

Talk about creating Grimrock 1 levels and mods here. Warning: forum contains spoilers!
User avatar
Redweaver
Posts: 68
Joined: Tue Dec 04, 2012 1:13 am
Location: Illinois, USA

Re: (WIP) Curious Conundrum / CFD 2012 submission

Post by Redweaver »

This is what I'm thinking so far:

Code: Select all

function checkAlcoveForItems()

   local firstSolutionFound = false
   local secondSolutionFound = false
   local firstBlueRight = false
   local firstGreenRight = false
   local firstRedRight = false
   local secondBlueRight = false
   local secondGreenRight = false
   local secondRedRight = false

for i in dungeon_alcove_1:containedItems() do
   if i.name == "blue_gem" then
      firstBlueRight = true
      break
   else
      firstBlueRight = false
      break
   end
end

for i in dungeon_alcove_4:containedItems() do
   if i.name == "red_gem" then
      firstRedRight = true
      break
   else
      firstRedRight = false
      break
   end
end

for i in dungeon_alcove_5:containedItems() do
   if i.name == "green_gem" then
      firstGreenRight = true
      break
   else
      firstGreenRight = false
      break
   end
end



if firstSolutionFound then
   playSound("level_up")
   exitdoor:open()
else
   exitdoor:close()
end

if secondSolutionFound then
   playSound("level_up")
   prizedoor:open()
else
   prizedoor:close()
end
Now there's just the missing IF/THEN section missing that checks if the firsts are true to set firstSolutionFound to true, and if the seconds are true, set secondSolutionFound to true...and where to put in the damage.

Code: Select all

function checkForSolution()

for i in dungeon_alcove_1:containedItems() do
   if i.name == "blue_gem" and

for i in dungeon_alcove_4:containedItems() do
   if i.name == "red_gem" and

for i in dungeon_alcove_5:containedItems() do
   if i.name == "green_gem" then

      exitdoor:open()
      break
   else
      spawn("poison_cloud", party.level, party.x, party.y, 0)

or

for i in dungeon_alcove_2:containedItems() do
   if i.name == "green_gem" and

for i in dungeon_alcove_3:containedItems() do
   if i.name == "red_gem" and

for i in dungeon_alcove_5:containedItems() do
   if i.name == "blue_gem" then

      prizedoor:open()
      break
   else
      spawn("poison_cloud", party.level, party.x, party.y, 0)

   end
end
end
end
end
end
end

how many of these ends do I need?

Does that work with an "OR" in it? Does that part after the "OR" need to be nested before the damage, so it looks for the first half, then if not true, checks the second set, THEN if both aren't true, damage.

Code: Select all

function checkForSolution()

for i in dungeon_alcove_1:containedItems() do
   if i.name == "blue_gem" and

for i in dungeon_alcove_4:containedItems() do  <-- unexpected symbol near "for"
   if i.name == "red_gem" and

for i in dungeon_alcove_5:containedItems() do
   if i.name == "green_gem" then

      exitdoor:open()
      break
   else
      
for i in dungeon_alcove_2:containedItems() do
   if i.name == "green_gem" and

for i in dungeon_alcove_3:containedItems() do
   if i.name == "red_gem" and

for i in dungeon_alcove_5:containedItems() do
   if i.name == "blue_gem" then

      prizedoor:open()
      break
   else
      spawn("poison_cloud", party.level, party.x, party.y, 0)

   end
   end
   end
   end
   end
   end
end
end
end
end
end
end
That looks like it could be right, but when I tried to test it, got "unexpected symbol near 'for'" thrown at the first "for" after the first "and".



Oh, and I still need to know how to recolor the lights from the temple_ceiling_light.
My finished mods:
A Curious Conundrum http://grimrock.nexusmods.com/mods/135 also on Steam Workshop

Current WIP:
Lair of Unarak http://grimrock.nexusmods.com/mods/137
User avatar
Grimwold
Posts: 511
Joined: Thu Sep 13, 2012 11:45 pm
Location: A Dungeon somewhere in the UK

Re: (WIP) Curious Conundrum / CFD 2012 submission

Post by Grimwold »

First thing you probably need is this little function that Petri wrote for us.. it takes 2 variables - alcove and item and checks to see if item is in alcove.. (put this in the SAME script entity that you plan to use for your alcove checks)

Code: Select all

-- 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

So we can call this with each pairing, like so:

Code: Select all

local green_correct = containsItem(dungeon_alcove_5,"green_gem")
local red_correct = containsItem(dungeon_alcove_4,"red_gem")
local blue_correct = containsItem(dungeon_alcove_1,"blue_gem")
if green_correct and red_correct and blue_correct then
  exitdoor:open()
  return true
end 
the reason I've created the xxx_correct variables is to do with how if and works... we want to test all 3 alcoves and if and will stop when it encounters a false result without performing the other checks (might be slightly unnecessary here, but good practice I think).

If it finds the right combination it opens the door and returns true (exiting the script).. we could then go on to run the same check again for the alternate combination.

Code: Select all

local green2_correct = containsItem(dungeon_alcove_2,"green_gem")
local red2_correct = containsItem(dungeon_alcove_3,"red_gem")
local blue2_correct = containsItem(dungeon_alcove_5,"blue_gem")
if green2_correct and red2_correct and blue2_correct then
  prizedoor:open()
  return true
end 
Since this test also exits with return true, we know that if the script carries on we have failed to find a solution... so we want to damage the party. Easy thing would be to spawn poison cloud... but if we are triggering this same script every time the player places an object in an alcove, then it will damage the player on inserting the 1st and 2nd gems correctly, so ideally we need to test if there are a total of 3 gems placed...

Code: Select all

local gem_count = 0
local alcove_list = {"dungeon_alcove_1","dungeon_alcove_2","dungeon_alcove_3","dungeon_alcove_4","dungeon_alcove_5","dungeon_alcove_6"}
for _,i in ipairs(alcove_list) do
  local alcove = findEntity(i)
    for j in alcove:containedItems() do
      if j.name:sub(-3) == "gem" then
        gem_count = gem_count + 1
      end
   end
end
if gem_count == 3 then
  spawn("poison_cloud", party.level, party.x, party.y, 0)
end
This will only spawn a cloud if there are 3 gems on the altar... and since we've already returned from the script if either of the combinations are found, the cloud will only spawn if the 3 gems are incorrect.


so putting this altogether in a function

Code: Select all

function checkAlcoves()
  local green_correct = containsItem(dungeon_alcove_5,"green_gem")
  local red_correct = containsItem(dungeon_alcove_4,"red_gem")
  local blue_correct = containsItem(dungeon_alcove_1,"blue_gem")
  if green_correct and red_correct and blue_correct then
    exitdoor:open()
    return true
  end 
  local green2_correct = containsItem(dungeon_alcove_2,"green_gem")
  local red2_correct = containsItem(dungeon_alcove_3,"red_gem")
  local blue2_correct = containsItem(dungeon_alcove_5,"blue_gem")
  if green2_correct and red2_correct and blue2_correct then
    prizedoor:open()
    return true
  end 
  local gem_count = 0
  local alcove_list = {"dungeon_alcove_1","dungeon_alcove_2","dungeon_alcove_3","dungeon_alcove_4","dungeon_alcove_5","dungeon_alcove_6"}
  for _,i in ipairs(alcove_list) do
    local alcove = findEntity(i)
      for j in alcove:containedItems() do
      if j.name:sub(-3) == "gem" then
          gem_count = gem_count + 1
        end
     end
  end
  if gem_count == 3 then
    spawn("poison_cloud", party.level, party.x, party.y, 0)
  end
end
and we want to trigger this function whenever an item is added/removed from an alcove.

note - this is untested code written from "memory", so may need a little tweaking.
Last edited by Grimwold on Tue Dec 04, 2012 4:56 pm, edited 1 time in total.
User avatar
msyblade
Posts: 792
Joined: Fri Oct 12, 2012 4:40 am
Location: New Mexico, USA
Contact:

Re: (WIP) Curious Conundrum / CFD 2012 submission

Post by msyblade »

you are such a bad@$$ grim. (sorry for the language, but it was necessary!)
Currently conspiring with many modders on the "Legends of the Northern Realms"project.

"You have been captured by a psychopathic diety who needs a new plaything to torture."
Hotel Hades
User avatar
Grimwold
Posts: 511
Joined: Thu Sep 13, 2012 11:45 pm
Location: A Dungeon somewhere in the UK

Re: (WIP) Curious Conundrum / CFD 2012 submission

Post by Grimwold »

Thanks :oops:


so I quickly tested the code and it worked great with a little tweak, which I've corrected above.

It's worth noting that this will only open the doors, and will not close them again if the gems are removed... this can easily be added by including a door:close() action at the very end of the script (perhaps using an if door:isOpen() check to make sure we're not calling close door on one that that is already closed!)
User avatar
Redweaver
Posts: 68
Joined: Tue Dec 04, 2012 1:13 am
Location: Illinois, USA

Re: (WIP) Curious Conundrum / CFD 2012 submission

Post by Redweaver »

Grimwold wrote:Thanks :oops:


so I quickly tested the code and it worked great with a little tweak, which I've corrected above.

It's worth noting that this will only open the doors, and will not close them again if the gems are removed... this can easily be added by including a door:close() action at the very end of the script (perhaps using an if door:isOpen() check to make sure we're not calling close door on one that that is already closed!)
That looks awesome. I'll copy/paste it and try it out.

Would it be too challenging to tweak that script so that it's called with a button press? So the player puts all the gems in place, then pushes a button to call the check for a solution?

Not a major deal, especially if this works in basically the way I'm looking for. Thanks!
My finished mods:
A Curious Conundrum http://grimrock.nexusmods.com/mods/135 also on Steam Workshop

Current WIP:
Lair of Unarak http://grimrock.nexusmods.com/mods/137
User avatar
Grimwold
Posts: 511
Joined: Thu Sep 13, 2012 11:45 pm
Location: A Dungeon somewhere in the UK

Re: (WIP) Curious Conundrum / CFD 2012 submission

Post by Grimwold »

Redweaver wrote: That looks awesome. I'll copy/paste it and try it out.

Would it be too challenging to tweak that script so that it's called with a button press? So the player puts all the gems in place, then pushes a button to call the check for a solution?

Not a major deal, especially if this works in basically the way I'm looking for. Thanks!
The script shouldn't need any changing to operate from a button push.. in fact it would be easier, as you would not need to connect each alcove to the script, but instead make a single connection from the button.

PS make sure you get the function at the top of my post, as well as the final check function... put them in the same script entity.
User avatar
Redweaver
Posts: 68
Joined: Tue Dec 04, 2012 1:13 am
Location: Illinois, USA

Re: (WIP) Curious Conundrum / CFD 2012 submission

Post by Redweaver »

Code: Select all

-- 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  <-- attempt to call method "containedItems" (a nil value)
    if i.name == item then
      return true
    end
  end
-- if we get here the item was not found
  return false
end

function checkAlcoves()
  local green_correct = containsItem(dungeon_alcove_5,"green_gem")
  local red_correct = containsItem(dungeon_alcove_4,"red_gem")
  local blue_correct = containsItem(dungeon_alcove_1,"blue_gem")
  if green_correct and red_correct and blue_correct then
    exitdoor:open()
    return true
  end 
  local green2_correct = containsItem(dungeon_alcove_2,"green_gem")
  local red2_correct = containsItem(dungeon_alcove_3,"red_gem")
  local blue2_correct = containsItem(dungeon_alcove_5,"blue_gem")
  if green2_correct and red2_correct and blue2_correct then
    orbdoor:open()
    return true
  end 
  local gem_count = 0
  local alcove_list = {"dungeon_alcove_1","dungeon_alcove_2","dungeon_alcove_3","dungeon_alcove_4","dungeon_alcove_5","dungeon_alcove_6"}
  for _,i in ipairs(alcove_list) do
    local alcove = findEntity(i)
      for j in alcove:containedItems() do
      if j.name:sub(-3) == "gem" then
          gem_count = gem_count + 1
        end
     end
  end
  if gem_count == 3 then
    spawn("poison_cloud", party.level, party.x, party.y, 0)
  end
end
Testing it out, put the gems into the correct alcoves, pushed the button and...fail. The error is in the code above.

Also, what item is intended to go into a mouth socket? I expected it to be the magic orb, but it wasn't.
My finished mods:
A Curious Conundrum http://grimrock.nexusmods.com/mods/135 also on Steam Workshop

Current WIP:
Lair of Unarak http://grimrock.nexusmods.com/mods/137
User avatar
Grimwold
Posts: 511
Joined: Thu Sep 13, 2012 11:45 pm
Location: A Dungeon somewhere in the UK

Re: (WIP) Curious Conundrum / CFD 2012 submission

Post by Grimwold »

Redweaver wrote:

Code: Select all

-- 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  <-- attempt to call method "containedItems" (a nil value)
    if i.name == item then
      return true
    end
  end
-- if we get here the item was not found
  return false
end

function checkAlcoves()
  local green_correct = containsItem(dungeon_alcove_5,"green_gem")
  local red_correct = containsItem(dungeon_alcove_4,"red_gem")
  local blue_correct = containsItem(dungeon_alcove_1,"blue_gem")
  if green_correct and red_correct and blue_correct then
    exitdoor:open()
    return true
  end 
  local green2_correct = containsItem(dungeon_alcove_2,"green_gem")
  local red2_correct = containsItem(dungeon_alcove_3,"red_gem")
  local blue2_correct = containsItem(dungeon_alcove_5,"blue_gem")
  if green2_correct and red2_correct and blue2_correct then
    orbdoor:open()
    return true
  end 
  local gem_count = 0
  local alcove_list = {"dungeon_alcove_1","dungeon_alcove_2","dungeon_alcove_3","dungeon_alcove_4","dungeon_alcove_5","dungeon_alcove_6"}
  for _,i in ipairs(alcove_list) do
    local alcove = findEntity(i)
      for j in alcove:containedItems() do
      if j.name:sub(-3) == "gem" then
          gem_count = gem_count + 1
        end
     end
  end
  if gem_count == 3 then
    spawn("poison_cloud", party.level, party.x, party.y, 0)
  end
end
Testing it out, put the gems into the correct alcoves, pushed the button and...fail. The error is in the code above.

Also, what item is intended to go into a mouth socket? I expected it to be the magic orb, but it wasn't.
Strange. it worked perfectly for me... can you check the IDs of the alcoves you are using for the puzzle.. I used the ones from your original post, but if one or more of those are missing/different in your dungeon, that could throw up the error.

This should be the list of IDs..
"dungeon_alcove_1","dungeon_alcove_2","dungeon_alcove_3","dungeon_alcove_4","dungeon_alcove_5","dungeon_alcove_6"

I'll have to get back to you about the mouth socket... I haven't used them and my memory from the main game is hazy. I'm pretty sure you could script it so that anything would go in it.
User avatar
Redweaver
Posts: 68
Joined: Tue Dec 04, 2012 1:13 am
Location: Illinois, USA

Re: (WIP) Curious Conundrum / CFD 2012 submission

Post by Redweaver »

Yes, the alcoves are numbered 1 - 6, and you got the right gems in the right places from my previous posts. The first part of the code, the bit from the top of your post that you told me to make sure to paste into the same script entity, seems a bit odd. It's refering to entities and items without defining them...is that right?

Next issue...I'm trying to attach a pair of timers, one with a 3 second count, one with a 5 second count each pointing a toggle command at a pit with a trap door. I'm trying to get the trap door to open and close in an odd cycling but predictable timing. Problem is, once each cycle through both timers the trapdoor looks like it is going from open to open without a close in between.

*edit*

Nevermind about the pits, I got the timing better. Mmmmmmmmmm, decimals. :D
My finished mods:
A Curious Conundrum http://grimrock.nexusmods.com/mods/135 also on Steam Workshop

Current WIP:
Lair of Unarak http://grimrock.nexusmods.com/mods/137
User avatar
Grimwold
Posts: 511
Joined: Thu Sep 13, 2012 11:45 pm
Location: A Dungeon somewhere in the UK

Re: (WIP) Curious Conundrum / CFD 2012 submission

Post by Grimwold »

Redweaver wrote:Yes, the alcoves are numbered 1 - 6, and you got the right gems in the right places from my previous posts. The first part of the code, the bit from the top of your post that you told me to make sure to paste into the same script entity, seems a bit odd. It's refering to entities and items without defining them...is that right?
Yes that's correct.. it's so you can pass it entities from your script.

I'm home for dinner and am just about to go out, so can't look at it right now, but when I get back on in a few hours I will create a test dungeon and set everything up.. then I can send you the working dungeon if necessary.
Post Reply