Opening LOTS of doors

Talk about creating Grimrock 1 levels and mods here. Warning: forum contains spoilers!
Grimfan
Posts: 369
Joined: Wed Jan 02, 2013 7:48 am

Opening LOTS of doors

Post by Grimfan »

Another question from a starting modder, so bear with me. ;)

What's the best way (in a script) for opening up lots of doors (like all 56 doors in a dungeon or 30 doors in a door maze). Furthermore, can you open up every door with one script regardless of the door type?

Thanks for any assistance as always. :)
User avatar
Xanathar
Posts: 629
Joined: Sun Apr 15, 2012 10:19 am
Location: Torino, Italy
Contact:

Re: Opening LOTS of doors

Post by Xanathar »

If you have grimq:

Code: Select all

grimq.fromAllEntitiesInWorld().where(grimq.isDoor):foreach(function(door) door:open(); end)
or

Code: Select all

for door in grimq.fromAllEntitiesInWorld().where(grimq.isDoor):toIterator() do
     door:open()
end

If you don't have grimq:

Code: Select all

for level = 1, getMaxLevels() do
	for entity in allEntities(level) do
		if (entity.setDoorState ~= nil) then
			entity:open()
		end
	end
end


Disclaimer: code not tested.
Waking Violet (Steam, PS4, PSVita, Switch) : http://www.wakingviolet.com

The Sunset Gate [MOD]: viewtopic.php?f=14&t=5563

My preciousss: http://www.moonsharp.org
User avatar
Komag
Posts: 3654
Joined: Sat Jul 28, 2012 4:55 pm
Location: Boston, USA

Re: Opening LOTS of doors

Post by Komag »

traditional method is to find some commonality in the name, so that a big "for i in allEntities(party.level) do" will be able to be useful, such as naming all your doors placed starting with the first four letters as "door" (so you have "doorTempleEntrance1", "doorDungeonGate4", etc)

Then you can do something like:

Code: Select all

  for i in allEntities(party.level) do
    if i.id:sub(1,4) == "door" then
       if i:isOpen() then
          i:close()
         else
          i:open()
       end
    end
  end
but now that we can check the "class" of entities, you can probably just do something much easier like:

Code: Select all

  for i in allEntities(party.level) do
    if i.class == "Door" then
       if i:isOpen() then
          i:close()
         else
          i:open()
       end
    end
  end
that way you don't have to set up any similar names at all.

By the way, those functions toggle the doors. If you just want to make sure they are all open then simplify it like this:

Code: Select all

  for i in allEntities(party.level) do
    if i.class == "Door" then
       i:open()
    end
  end
and if you're like me and prefer to squish the code a bit, you can do this:

Code: Select all

  for i in allEntities(party.level) do
    if i.class == "Door" then i:open() end end
Finished Dungeons - complete mods to play
User avatar
msyblade
Posts: 792
Joined: Fri Oct 12, 2012 4:40 am
Location: New Mexico, USA
Contact:

Re: Opening LOTS of doors

Post by msyblade »

Good stuff, Komag , Possibly even Superthread good :)
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
Grimfan
Posts: 369
Joined: Wed Jan 02, 2013 7:48 am

Re: Opening LOTS of doors

Post by Grimfan »

Thanks for the great assistance guys. :D

I have your grimq Xanathar, but haven't implemented it in my dungeon, since I want to learn how to lua script normally and your great work sortta makes things too easy for us beginners. My next dungeon will definitely be using it however, since I see how it can speed scripting up.

And your explanation would be great in the editing superthread Komag. :) It's because I didn't see it there that I asked this question (I knew it had to do with that pesky i however).

Now, I might as well ask another question while I'm here instead of cluttering up the boards with another thread.

I know I can modify the attack power of a party with a script. I just need to know what it would look like. Would it be something like this:

Code: Select all

for i = 1,4 do
party:getChampion(i):modifyAttackPower(20)
or something like this:

Code: Select all

for i = 1,4 do
party:getChampion(i):modifystat("attack power", 20)
or something else entirely (I don't know if it's even called attack power actually)?

Also, how can I make it so a change only lasts a certain number of minutes? Would it be better with a timer connected to the script or just a hidden pressure plate?

EDIT1: Well, it's definitely not called attack power or attackPower.
EDIT2: Okay, so it's not even a stat that can be modified according to the modding guide. Mmm...
EDIT3: Okay, so how can I make the character temporarily deal more damage (trainSkill or modifyStat strength seems the only obvious options).
User avatar
Komag
Posts: 3654
Joined: Sat Jul 28, 2012 4:55 pm
Location: Boston, USA

Re: Opening LOTS of doors

Post by Komag »

done :)
Finished Dungeons - complete mods to play
User avatar
Frenchie
Posts: 219
Joined: Wed Oct 16, 2013 2:50 am

Re: Opening LOTS of doors

Post by Frenchie »

This "opening all doors" would be really good if someone has killed the end boss but wants to explore the dungeon for things he missed. Besides doors it should also open all secret walls and destroy all invisible walls.
Glew
Posts: 74
Joined: Sat Dec 21, 2013 7:57 pm

Re: Opening LOTS of doors

Post by Glew »

Okay, so this is the closest thread I could find to my problem(s).

1: Is there any way at all to only affect a certain group of stuff [for the lack of the terminus technicus]. e.g doors in one given room. Or should I just man up and add connectors to all 9-10 doors separately and manually? Other example: to activate all spawners in a room (this may or may not serve the purpose of filling the room with poison gas :twisted: )

2: Is there a way to spawn the same (kind of) stuff all over a grid? e.g. to fill a room with poison gas.
So instead of doing this:

Code: Select all

function yadda_yadda()
spawn("poison_cloud", 2, 20, 13, 1)
spawn("poison_cloud", 2, 19, 13, 1)
spawn("poison_cloud", 2, 21, 13, 1)
spawn("poison_cloud", 2, 18, 13, 1)
spawn("poison_cloud", 2, 20, 14, 1)
spawn("poison_cloud", 2, 19, 14, 1)
spawn("poison_cloud", 2, 21, 14, 1)
spawn("poison_cloud", 2, 18, 14, 1)
-- repeat ad nausam
end
Can I use some dirty trick to spawn a poison cloud on all tiles in a square let's say from x:1 y:1 to x:3 y:3?
User avatar
JohnWordsworth
Posts: 1397
Joined: Fri Sep 14, 2012 4:19 pm
Location: Devon, United Kingdom
Contact:

Re: Opening LOTS of doors

Post by JohnWordsworth »

I'll start with the second question, as it's super easy to do. Where you have a grid like that, you can just use a double loop over the x,y variables. For instance;

2. Spawning a Grid of Entities

Code: Select all

-- Spawn a grid of the same type of entity.
-- @param entityName The entity to spawn.
-- @param level The level on the dungeon to spawn the entities on
-- @param minX The first X coordinate to spawn in
-- @param maxX The last X coordinate to spawn in
-- @param minY The first Y coordinate to spawn in
-- @param maxY The last Y coordinate to spawn in
-- @param facing All entities will be spawned with this facing
--
function spawn_grid(entityName, level, minX, minY, maxX, maxY, facing)
  for x=minX, maxX do
    for y=minY, maxY do
      spawn(entityName, level, x, y, facing);
    end
  end
end
1. Opening all doors in a given region: Using a similar method, you can scan through all of the entities in a region and do the same as above. So, for instance, the simple solution is;

Code: Select all

-- Open all doors in the region between (minX, minY) and (maxX, maxY) on the given floor.
-- 
function open_all_doors(level, minX, minY, maxX, maxY)
  for x = minX, maxX do
    for y = minY, maxY do
      for e in entitiesAt(level, x, y) do
        if ( e.class == "Door" ) then
          if ( e:isClosed() ) then
            e:open();
          end
        end
      end
    end
  end
end
Note that, repeatedly calling entitiesAt isn't particularly fast - so you wouldn't want to do this sort of thing every frame. However, if it's just an effect that happens when you push a button or kill a monster say - then it's definitely not a problem performance wise.
My Grimrock Projects Page with links to the Grimrock Model Toolkit, GrimFBX, Atlas Toolkit, QuickBar, NoteBook and the Oriental Weapons Pack.
Glew
Posts: 74
Joined: Sat Dec 21, 2013 7:57 pm

Re: Opening LOTS of doors

Post by Glew »

Thanks a lot! This will hopefully make life easier. (Well, I just realised that it isn't as easy as I thought at first glimpse :( )

So a potential script would look like this? Just to see if I got this right (I probably haven't):

Code: Select all

function PoisonRoom("poison_cloud", 1, 15, 15, 17, 17, 1) -- to fill a room from 15;15 to 17;17 with poison
  for x=15, 17 do
    for y=15, 17 do
      spawn("poison_cloud", 1, 15, 15, 1) --This is where I think I have no idea what I'm doing
    end
  end
end
Question: Why do I need to give all the stuff after the function name (I always left the brackets empty before now)

edit:
Oh, on a second thought, maybe like this:

Code: Select all

function PoisonRoom("poison_cloud", 1, 15, 15, 17, 17, 1) -- still no idea why this is here though
  for x=15, 17 do
    for y=15, 17 do
      spawn("poison_cloud", 1, x, y, 1) -- putting x and y in here which have been previously defined?????????
    end
  end
end
Post Reply