How to find the trigger of an entity

Talk about creating Grimrock 1 levels and mods here. Warning: forum contains spoilers!
Post Reply
User avatar
Frenchie
Posts: 219
Joined: Wed Oct 16, 2013 2:50 am

How to find the trigger of an entity

Post by Frenchie »

I've been thinking about a hint system working as a djinn in an oil lamp. You rub it to activate it and it gives you a number of wishes. You either pay for them with coins, gems or it has a counter granting you a limited amount of wishes per level. Some wishes might count as double or you might not even have enough credits. He could even refuse you at specific places.

As for the duration of certain wishes I could use the Counter option although I'm not sure how I decrease it for each movement the party makes.

With setStat, setStatMax I could give a statt enhancement, for example extra strength. I could open a door with setDoorState, open() or let you jump over a pit with setPosition.

Coming back to the topic, I want to find a key of an unknown lock. The following function will find it:

function LockSpy()
fa = party.facing
le = party.level
xx = party.x
yy = party.y
dx, dy = getForward(fa)
for e in entitiesAt(le, xx, yy) do
if e.class == "Lock" and e.facing == fa then LockFound()
end
end
for e in entitiesAt(le, xx + dx, yy + dy) do
if e.class == "Lock" and e.facing == (fa + 2) % 4 then LockFound()
end
end
end

The above might look double, but it's a fail safe for locks in doors that have the opposite facing. In the function LockFound() I want to show the name of the lock e.name, but I don't know how to find its trigger the "key". The below function is a rough idea how I would like to continue:

function LockFound()
lock = e.name
key = keyName
key.x, key.y, key.level = findEntity(key)
hudPrint "The lock you're looking at is ",lock, "and its key ",
key, "can "
if keyLevel == party.level then hudPrint key, "be found at
(",key.x,",",key.y") on this level"
else hudPrint "not be found on this level"
end

I know I have to use allEntities(party.level) to get all the available keys if there are multiple keys with the same name. This will only show the first key it finds, which might not even be on the party's level. I also don't want to give all the locations of those keys, but the closest one on the same level!
User avatar
DesperateGames
Posts: 90
Joined: Sun Oct 06, 2013 1:54 pm

Re: How to find the trigger of an entity

Post by DesperateGames »

Hello Frenchie,

that djinn idea sounds exciting! However I cannot think of a way to access the type of key that opens a lock or a locked door...the scripting reference doesn't mention a way to get this during runtime. Unless somebody comes up with a trick, I would create a script entity to maintain a lua table that stores IDs of doors/locks and the types / IDs of the keys that will unlock it. You would need to maintain the table manually as you build your mod, but unless you are not going crazy with locked doors it would be a doable workaround I think.
User avatar
msyblade
Posts: 792
Joined: Fri Oct 12, 2012 4:40 am
Location: New Mexico, USA
Contact:

Re: How to find the trigger of an entity

Post by msyblade »

I would also suggest making a unique key for every lock, and since there is only one key for any given lock, you wouldn't need to worry about finding multiple iterations. No need to make new models or icons, just clone keys and call them "Gold_Key_C" or similar. However, this can limit certain puzzle types where the player has 2 keys and must choose from 4 doors, or you could have the djinn say "I cannot help you with this decision" on a puzzle like that.
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
Isaac
Posts: 3192
Joined: Fri Mar 02, 2012 10:02 pm

Re: How to find the trigger of an entity

Post by Isaac »

Alternatively... You could make your locks alcoves (that use the lock model) instead and let them open open a door via a key place in them (and destroyed), or due to a wish ~probably via the onInsertItem() hook. In this way, you could have more than one "key"; the wish could use a special item to unlock ~despite whatever the key actually was.

If you wanted to get really fancy, you could make the alcove not destroy the key, but rather not accept anything but the key, and not let it be taken back... and set the alcove's placement of keys to look exactly like the key sticking out of the lock. I suppose wishes could open the lock, or provide a key to it.
User avatar
Frenchie
Posts: 219
Joined: Wed Oct 16, 2013 2:50 am

Re: How to find the trigger of an entity

Post by Frenchie »

My LUA knowledge is far below average, but I wonder if the following can be used for my goals.

Let's assume there are logically named entities like door_gold, lock_gold and a gold_key. I don't know if there is a command like data.get("door_gold", "lock_gold") that returns "gold_key". It would require me to also find the door entity belonging to the lock, which I might not even face if it's a wall lock.

With a split("lock_gold","_") I might cut the type from the class, but I don't know if there's a join("gold","_","key") command to get the key.

I also wonder if an identical lock has been opened in the past with a key, we could store those names and use them in the functions. Then the djinn just needs to retrieve the log data.
User avatar
Isaac
Posts: 3192
Joined: Fri Mar 02, 2012 10:02 pm

Re: How to find the trigger of an entity

Post by Isaac »

Frenchie wrote:...
As far as I am aware... The locks in the game simply do not expose their key ~there is no way to check or compare to find out what it is. Locks also do not respond to any events other than the use of their key ~no way to trigger them by script or other switch AFAIK.

Now one could meticulously name every lock and keep a list (as was mentioned); or define a new alcove and change the model reference to one that is used by a lock; use the gold lock model, and the alcove would look like a gold lock ~it would take anything though, you would want to script restrictions via the onInsertItem hook. The advantage is that you would have the options available from alcoves ~which are more than locks offer, and includes the option to open a door (just like locks) ~but also the option to run scripts.

** There is {I suppose} the possibility that one of the frameworks has additional options, but I've not used them often, nor am I well acquainted with their features. JKos, Diarmuid, and Xanathar are the ones to ask.
User avatar
DesperateGames
Posts: 90
Joined: Sun Oct 06, 2013 1:54 pm

Re: How to find the trigger of an entity

Post by DesperateGames »

I don't know if there is a command like data.get("door_gold", "lock_gold") that returns "gold_key". It would require me to also find the door entity belonging to the lock, which I might not even face if it's a wall lock.
I hope I understood this correctly: At the moment the player uses / calls the djinn, you have the id of the lock, and you would require to get the id of the door that will be opened by that lock and the id of the key that will unlock this lock, right?

Option 1:

You could do the following: Create a script called "lockDatabase":

Code: Select all

lockData1={lockId="lock_gold",doorID="door_gold",keyID="key_gold"}
lockData2={lockId="lock_silver",doorID="door_silver",keyID="key_silver"}
lockData3={lockId="lock_bronze",doorID="door_bronze",keyID="key_bronze"}

lockTable={}

table.insert(lockTable,lockData1)
table.insert(lockTable,lockData2)
table.insert(lockTable,lockData3)

function getDoorForLockId(lockId)
	for index,data in pairs(lockTable) do
		if data.lockId == lockId then
			return data.doorID		
		end
	end
end

function getKeyForLockId(lockId)
	for index,data in pairs(lockTable) do
		if data.lockId == lockId then
			return data.keyID		
		end
	end
end
Now you can call these two functions to get the door and the key for a lock anywhere, for example if you put

Code: Select all

print(lockDatabase.getDoorForLockId("lock_silver"))
in a different script you will get "door_silver" printed on the screen. The downside would be that you need to add two new lines in the lockDatabase script every time you add a new lock. And you would need to be careful when renaming doors and locks because you need to maintain the changes in the lockDatabase as well. :cry: But on the positive side this should resolve your problem quickly ;)

Option 2:

If your IDs for the locks, doors and keys are really that consistent and simple like in your example, you could also do the following:

Code: Select all

function getDoorForLockId(lockId)
	return findEntity("door_"..split(lockId, "_")[2])
end

function split(inputstr, sep)
        if sep == nil then
                sep = "%s"
        end
        t={} ; i=1
        for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
                t[i] = str
                i = i + 1
        end
        return t
end
this function would return the door object / table for a given lock ID assuming the door are always named like in your example above. The extra "split" function does the magic of separating the string at the "_" character.

I hope one of these was what you needed or at least they gave you fresh (french :D ) ideas ;)
Post Reply