Altar and counter

Talk about creating Grimrock 1 levels and mods here. Warning: forum contains spoilers!
User avatar
DeDy
Posts: 132
Joined: Sun Oct 07, 2012 3:41 pm
Location: Brno, Czech Republic

Altar and counter

Post by DeDy »

Hi, please need help. 3x Ogre hammer stay on altar = open door. Remove hammer = door close.

Thanks

function OgreAltar()
for i in altar_3:containedItems() or altar_4:containedItems() or altar_5:containedItems() do
if i.name == "ogre_hammer" then
dungeon_door_portcullis_17:open()
dungeon_door_portcullis_18:open()
end
end
end
Nightfall: First Contact – http://dedy.euweb.cz/nightfall.html
User avatar
Kuningas
Posts: 268
Joined: Wed Apr 11, 2012 10:29 pm
Location: Northern Finland

Re: Altar and counter

Post by Kuningas »

I am actually working on a similar case -- three gems on an altar (actually 3 altars on each other). But it is incomplete -- putting them on the altar opens the door, but so does putting one of them three times. Also, taking one out and putting it again will close it (because the counter is still active, should remove it as well).

It is also more than a bit rough, but maybe it will be of some help. It can probably be done more elegantly:

Code: Select all

--WARNING, this code is incomplete! It works, but not completely as intended
--you will need three alcoves (here: waltars 1, 2 and 3), a counter (here: gemcounter), a secret door (here: gemdoor) and this script in a  script entity.

function gemcheckfunc()

   for i in waltar1:containedItems() do
      if i.name == "green_gem" then
         gemcounter:increment()
	  if i.name == "blue_gem" then
		 gemcounter:increment()
	  if i.name == "red_gem" then
		 gemcounter:increment()
	  end
      end
	  end
	end

   for o in waltar2:containedItems() do
      if o.name == "green_gem" then
         gemcounter:increment()
	  if o.name == "blue_gem" then
		 gemcounter:increment()
	  if o.name == "red_gem" then
		 gemcounter:increment()
	  end
      end
	  end
	end

   for p in waltar3:containedItems() do
      if p.name == "green_gem" then
         gemcounter:increment()
	  if p.name == "blue_gem" then
		 gemcounter:increment()
	  if p.name == "red_gem" then
		 gemcounter:increment()
	  end
      end
	  end
	end

	if gemcounter:getValue() == 3 then
	gemdoor:open()
	else
	gemdoor:close()
	end
end
I'll report in again if I find a solution.

EDIT: viewtopic.php?f=14&t=3083 may also be of use, that is where I learned this much.
BASILEUS
User avatar
Filipsan
Posts: 84
Joined: Fri Mar 16, 2012 10:18 am

Re: Altar and counter

Post by Filipsan »

Try somethingl like this (not tested)

Code: Select all


function gemcheckfunc()

    checkAltar(waltar1)
    checkAltar(waltar2)
    checkAltar(waltar3)

    if gemcounter:getValue() == 3 then
        gemdoor:open()
    else
        gemdoor:close()
    end
end

function checkAltar(altar)
    for i in altar:containedItems() do
        if i.name == "green_gem" then
            gemcounter:increment()
        elseif i.name == "blue_gem" then
            gemcounter:increment()
        elseif i.name == "red_gem" then
            gemcounter:increment()
        else
            gemcounter:decrement()
        end
    end
end
User avatar
Grimwold
Posts: 511
Joined: Thu Sep 13, 2012 11:45 pm
Location: A Dungeon somewhere in the UK

Re: Altar and counter

Post by Grimwold »

I haven't tested it, but Filipsan's script looks like it's on the right lines.. the important thing when using a counter is to increment and decrement it when objects are removed/added to the alter

Since counters automatically activate when they reach 0 it's best to have them count down instead of up... so set the initial value to 3... then when the right item is added to the alter decrement the counter. If the item is removed then increment the counter to avoid the situation of using 1 item 3 times!

You'll also need to make the altar trigger on ANY event, otherwise it will only trigger when the first object is added or the last one is removed.
User avatar
Kuningas
Posts: 268
Joined: Wed Apr 11, 2012 10:29 pm
Location: Northern Finland

Re: Altar and counter

Post by Kuningas »

Good tips! My altars are actually alcoves at the moment, but it seems to work all the same. I never knew I could write the script that way, looks very logical to me.

I figure I could just add a hook to the objects so one can't remove gems from these altars/alcoves, I doubt I'll use them again in this dungeon. ( just need to remember this if there are gems around if I use them again)

EDIT: ARGH! There is no RemoveItem hook? Damn!
BASILEUS
User avatar
Filipsan
Posts: 84
Joined: Fri Mar 16, 2012 10:18 am

Re: Altar and counter

Post by Filipsan »

User avatar
Kuningas
Posts: 268
Joined: Wed Apr 11, 2012 10:29 pm
Location: Northern Finland

Re: Altar and counter

Post by Kuningas »

Thanks! I actually finally found a way to do it like I originally intended, but I am sure this will be handy in the future.
BASILEUS
User avatar
DeDy
Posts: 132
Joined: Sun Oct 07, 2012 3:41 pm
Location: Brno, Czech Republic

Re: Altar and counter

Post by DeDy »

Hmmm, not work :( Im not programmer, only artist.
Please help.

Counter Initial Value = 3
Event = any

Code: Select all

function OgreAltar()
	for i in altar_ogre1:containedItems() do
		if i.name == "ogre_hammer" then
		counter_orge_altar:decrement()
	end
end

	for o in altar_ogre2:containedItems() do
		if o.name == "ogre_hammer" then
		counter_orge_altar:decrement()
	end
end

	for p in altar_ogre3:containedItems() do
		if p.name == "ogre_hammer" then
		counter_orge_altar:decrement()
	end
end

	if counter_orge_altar:getValue() == 0 then
		dungeon_door_portcullis_17:open()
		dungeon_door_portcullis_18:open()
			else
		dungeon_door_portcullis_17:close()
		dungeon_door_portcullis_18:close()
	end
end
Nightfall: First Contact – http://dedy.euweb.cz/nightfall.html
User avatar
Komag
Posts: 3659
Joined: Sat Jul 28, 2012 4:55 pm
Location: Boston, USA

Re: Altar and counter

Post by Komag »

They should be separate functions I think: (and watch the spelling on ogre)

Code: Select all

function OgreAltar1()
  for i in altar_ogre1:containedItems() do
    if i.name == "ogre_hammer" then
      counter_ogre_altar:decrement()
    end
  end
  checkOgreAltar()
end

function OgreAltar2()
  for i in altar_ogre2:containedItems() do
    if i.name == "ogre_hammer" then
      counter_ogre_altar:decrement()
    end
  end
  checkOgreAltar()
end

function OgreAltar3()
  for i in altar_ogre3:containedItems() do
    if i.name == "ogre_hammer" then
      counter_ogre_altar:decrement()
    end
  end
  checkOgreAltar()
end

function checkOgreAltar()
  if counter_ogre_altar:getValue() == 0 then
    dungeon_door_portcullis_17:open()
    dungeon_door_portcullis_18:open()
  else
    dungeon_door_portcullis_17:close()
    dungeon_door_portcullis_18:close()
  end
end
But that is actually problematic because a player could place a hammer on one altar three times and the doors would open. If you build in an "else increment counter" for each script, anytime they place another object on the altar the counter would go up, causing problems. Might work better just to do single altar scripts like you can find all over the forums, then just link all of them to a counter properly set up, and that to the doors.
Finished Dungeons - complete mods to play
User avatar
Kuningas
Posts: 268
Joined: Wed Apr 11, 2012 10:29 pm
Location: Northern Finland

Re: Altar and counter

Post by Kuningas »

I feel bad for almost hijacking your topic, so here is a working code (courtesy of Grimwold -- I'd still be swearing with my door were it not for him and all the other helpful people here, so this code basically isn't mine -- credit to the one who deserves it, I am just a messenger here ; D)

Basically, you'll want the game to check the altars every time the party takes something from them or places something on them. There are a few ways to do this, but the simplest is to connect the altars to a script entity which can then check what the item on the altar is (if any). You won't need a counter, because all the altars are checked every time an item is placed on one of them or taken from one of them.

You'll need three altars for this (I named them hammeraltar1 hammeraltar2 and hammeraltar3, you can call them whatever you want, just be sure to change the names from the script as well), a script entity (name doesn't matter, because you can activate the functions by connecting the altars straight to the script entity -- it might be wise to name it something logical, though.)

JUST MAKE SURE YOU HAVE "activate always" TICKED FROM THE ALTARS' PROPERTIES, AND THE EVENT PART SET TO "any", AND ACTION PART SET TO THE FUNCTION I CALLED "contentcheck". (again, you can name it what you want, just be sure to alter the name in the script as well)

Sorry for yelling, but this was the reason I was stuck for a long time. With activate always the altar will trigger the function also when an item is removed from it -- necessary because we want the door to close if a hammer is removed.

You'll also need the secret door you want to open, I named it hammerdoor. Same applies -- name it what you want, but make sure the script has the same name.

Here is the complete code, I will go through it line by line afterwards:
SpoilerShow

Code: Select all

function hammercheck(altar)
	for i in altar:containedItems() do
		if i.name == "ogre_hammer" then
			return true
		end
	end
	return false
end

function contentcheck()
	if hammercheck(hammeraltar1) and hammercheck(hammeraltar2) and hammercheck(hammeraltar3) then
		hammerdoor:open()
		else
		hammerdoor:close()
	end
end


function hammercheck(altar) -- this function will be used to determine what items are on the altar and if our desired item is there, as follows

for i in altar:containedItems() do -- this just means that the game will go through all the items on the altar

if i.name == "ogre_hammer" then -- this means that if one of the items is called ogre_hammer, the next will happen

return true -- this will stop the loop and give true, "positive" result if the ogre_hammer is on the altar - the contentcheck function will use this information

end

end

return false -- if an ogre_hammer was not on the altar, this will end the function and return a false "negative" result. Again the other function will use this to decide if it opens the door or closes it

end


function contentcheck() -- this function will "use" the previous function on the altars you have in your map, and if all the altars give a positive result (the hammer is there), it will open the door

if hammercheck(hammeraltar1) and hammercheck(hammeraltar2) and hammercheck(hammeraltar3) then -- this checks the altars one at a time, if all the altars give the "true" result the next will happen

hammerdoor:open() -- this happens, the door opens; if it is already open, it will stay open.

else -- If not, (all the altars didn't have a hammer)

hammerdoor:close() -- this happens. This way if the party removes a hammer, the door will close immediately; if it is already closed, it will stay closed.

end

end

I hope I explained it clear enough, I tried to do so because I personally had much trouble understanding this script, not because it was unclear, but because certain scripting principles were unclear to me.
BASILEUS
Post Reply