Ask a simple question, get a simple answer

Ask for help about creating mods and scripts for Grimrock 2 or share your tips, scripts, tools and assets with other modders here. Warning: forum contains spoilers!
User avatar
KhrougH
Posts: 76
Joined: Tue Sep 04, 2018 11:45 pm
Location: Roma

Re: Ask a simple question, get a simple answer

Post by KhrougH »

Isaac wrote: Wed Oct 17, 2018 8:38 am There is a built in iterator for this. ;)

Code: Select all

for level = 1, Dungeon:getMaxLevels() do
	for obj in Dungeon.getMap(level):allEntities() do 
		if obj.lock or obj.door then

			print('Name:',obj.name, "ID:" obj.id, "Level:",obj.level)

		end	
	end
end	
Excellent, i wil work on this. not sure i can understand what's going on in there :lol: :lol: :lol:
*Also... KhrougH, there is a better and more up-to-date scripting reference than the one featured on this site; (thanks to JKos and minmay).
https://github.com/JKos/log2doc/wiki
good, i'll give i look, i need to learn much more about lua scripting and specially the LoG2 references
** In the above (spoilered) condition: if (DL or OD) == nil then break ...end, it only breaks if DL and OD are both nil at the same time—and not when just one of them is nil. That's a crash if it ever finds one but not both.
it never crashed because i have a door for every lock so they have the same number. i mean for lock_1 i have door_1 , for lock_'n' i have door_'n'. but of corse my ignorance about script is pretty clear :oops: i will change it.

thank you, Isaac
[...]
All those moments will be lost in time, like tears in rain.
Time to die.
User avatar
KhrougH
Posts: 76
Joined: Tue Sep 04, 2018 11:45 pm
Location: Roma

Re: Ask a simple question, get a simple answer

Post by KhrougH »

Isaac wrote: Wed Oct 17, 2018 8:38 am There is a built in iterator for this. ;)
SpoilerShow

Code: Select all

for level = 1, Dungeon:getMaxLevels() do
	for obj in Dungeon.getMap(level):allEntities() do 
		if obj.lock or obj.door then

			print('Name:',obj.name, "ID:" obj.id, "Level:",obj.level)

		end	
	end
end	
ok, but because i don't need it in every map my code now is like this:

Code: Select all

--for level = 1, Dungeon:getMaxLevels() do
	for obj in Dungeon.getMap(11):allEntities() do 
		if obj.lock then

			--print("Name: " ,obj.name, "ID: ", obj.id, "Level: ", obj.level)
			
			obj.model:setOffset(vec(-1.15,1.2,-0.01))
			obj.clickable:setOffset(vec(-1.15,1.2,-0.01))
		end	
		
		if obj.door then
			myobj = "town_door_wooden_"..string.match(obj.id, "%d+")
			if obj.id ==  myobj then
				obj.clickable:disable()
			end	
		end
	end
--end	
does it looks nice for you?

now this script can identify the objects on the maps, on every maps. but what i need is to identify the object I'M USING.
in my specified case i have to identify the lock i'm unlocking for "clickable:enable()"ing his relative door.
i could give an id name with same number to lock and door and than using the "string.match( [lock] , "%d+" )" to find the correct door. but i don't know how to recognize the lock i'm unlocking.
[...]
All those moments will be lost in time, like tears in rain.
Time to die.
User avatar
Isaac
Posts: 3185
Joined: Fri Mar 02, 2012 10:02 pm

Re: Ask a simple question, get a simple answer

Post by Isaac »

The lock object —if that's what is calling your function— is the first argument that the function gets when it's called; you can inspect it. The argument is automatic from connected objects. In user scripts, it depends on the calling syntax.
Example:

Code: Select all

--Must use the Game Object:  .go

function lockManager(caller)
	
	if caller.go and caller.go.lock then
		print(caller.go.name, caller.go.id)		
		for target = 1, caller.go.lock:getConnectorCount() do
			local _,connector = caller.go.lock:getConnector(target)
			print("Lock opens:", connector)
		end	
	end
		
end
User avatar
KhrougH
Posts: 76
Joined: Tue Sep 04, 2018 11:45 pm
Location: Roma

Re: Ask a simple question, get a simple answer

Post by KhrougH »

Isaac wrote: Wed Oct 17, 2018 6:15 pm The lock object —if that's what is calling your function— is the first argument that the function gets when it's called; you can inspect it. The argument is hidden, and automatic from connected objects. In user scripts, it depends on the calling syntax.
Example:
SpoilerShow

Code: Select all

--Must use the Game Object:  .go

function lockManager(caller)
	
	if caller.go and caller.go.lock then
		print(caller.go.name, caller.go.id)		
		for target = 1, caller.go.lock:getConnectorCount() do
			local _,connector = caller.go.lock:getConnector(target)
			print("Lock opens:", connector)
		end	
	end
		
end
here we go... Pandora's box is open!!! :o
when i use this script the Key doesn't disappear but the locks open
(errata corrige: I'M SORRY MY MISTAKE I WAS USING A MASTER_KEY... of corse it opens all doors and never disappears)
and the "connector" is the same script, because i didn't connected the lock to the door.

but there are some things in this function i really don't know what does they do
for example "local _, connector" ... it should be a variable but what the underscore does?
and what's the difference between "caller.go" and "caller.go.lock"?
can you explain what this function does?

i made some more proves and i modified it, but there's still something i don't understand.
here is the new function:
SpoilerShow

Code: Select all

function lockManager(caller)
	
	if caller.go and caller.go.lock then
		--print(caller.go.name, caller.go.id)		
		local target =  findEntity("town_door_wooden_"..string.match(caller.go.id, "%d+"))
			--print("Lock opens:", target)
			target.clickable:enable()
	end		
end
at the beginning i used
target = "town_door_wooden_"..string.match(caller.go.id, "%d+")

and it was working for "print" but not for "clickable". i wonder why?
with findEntity it prints "table [number]" but clickable works good.
i think i'mm missing something in script understanding.
[...]
All those moments will be lost in time, like tears in rain.
Time to die.
User avatar
Isaac
Posts: 3185
Joined: Fri Mar 02, 2012 10:02 pm

Re: Ask a simple question, get a simple answer

Post by Isaac »

KhrougH wrote: Wed Oct 17, 2018 8:20 pm ..."local _, connector" ... it should be a variable but what the underscore does?
The underscore (used in this way) means to discard/ ignore the value. The getConnector function returns three string values; the hook action, the connected object, and the function it calls. I only needed to print the name of the connected object, so the assignment ignores the first and last of the three return values.

...and what's the difference between "caller.go" and "caller.go.lock"?
can you explain what this function does?
It's generally good to err on the side of caution. This condition first checks for .go
before checking for a lock component; it shouldn't ever fail... but there are calling situations that would not have a .go property in the variable; so I check for it—if it's ever not there, then something is already wrong with it.

The .go property gives access to the game object—from within its own components.
...it was working for "print" but not for "clickable". i wonder why?
The door component has its functionality within it, and doesn't use the clickable component—so by default the doors don't have one.
(But some of yours might, if they are custom door objects.)
User avatar
KhrougH
Posts: 76
Joined: Tue Sep 04, 2018 11:45 pm
Location: Roma

Re: Ask a simple question, get a simple answer

Post by KhrougH »

here i go with another annoying question:

there's any chance i can activate a lock with 2 different keys?
my intention is having a specific key for the lock but having the chance to unlock it also with a "lock_pick". which is a realistic way to open a door if you don't have the key.

i tried with
lock.lock:setOpenedBy("iron_key", "pick_lock")
but only the first works.
i'm going to try something like onClick... getMouseItem...
well, i don't know. open to suggestions.
[...]
All those moments will be lost in time, like tears in rain.
Time to die.
Pompidom
Posts: 497
Joined: Sun May 06, 2018 9:42 pm

Re: Ask a simple question, get a simple answer

Post by Pompidom »

Don't bother with mechanics that can be skipped with save scumming.

If I break my lock pick by random chance I will instantly console spawn another lockpick or savescum (save/reload) until that door is open.

Offcourse this is my personal opinion, but I've seen many discussions about these mechanics in the past and every single time the big majority will simply cheat their way around it because it's plain annoying in a single player game.

In my Blood Moon mod, all my puzzles and mechanics are immune to save scumming and to a certain degree of console cheats.
Also trial and error approach won't work.
User avatar
Isaac
Posts: 3185
Joined: Fri Mar 02, 2012 10:02 pm

Re: Ask a simple question, get a simple answer

Post by Isaac »

One need not include the standard lock_pick definition. :twisted:

Code: Select all

	defineObject{
	name =  [[A356_55AC49292CB0]],
	baseObject = "base_item",
	components = {
		{
			class = "Model",
			model = "assets/models/items/lockpicks.fbx",
		},
		{
			class = "Item",
			uiName = "Lock Picks",
			stackable = true,
			gfxIndex = 356,
			weight = 0.2,
		},
		{
			class = "Particle",
			particleSystem = "glitter_silver",
		},
	},
}
*It's interesting that 'Eye of the Beholder' had lock picks, and it had the keys pre-placed, but anytime you successfully picked a lock... one of those keys disappeared. You couldn't actually save keys by picking locks.
Pompidom
Posts: 497
Joined: Sun May 06, 2018 9:42 pm

Re: Ask a simple question, get a simple answer

Post by Pompidom »

https://youtu.be/_B2JaMQl3sY

4 gate controls puzzle

The current situation: The rock from the dispenser (the only rock in the game) basically falls on a pressure plate which activates a teleporter that spawns the rock back at your feet. And you will have to throw the same rock on the same weight platforms over and over again.
As can be seen, the puzzle works and is basically finished. It's basically like a numbered bike lock.
The platform lowering animation is just for show.

However, I want the rock to be "teleported" to the surface of the rock dispenser (the dungeon alcove)

Or simply destroy the rock when it hits the pressure plate and then simply create a new rock in the rock dispenser.

Basically I just want to avoid my mod slowing down with a thousand rocks lying in a pit when people keep throwing stones willy nilly trying to crack the code.

Any advice or code to accomplish this?

Something like this, but since a pressure plate doesn't have a surface component, I don't really know how to do it or wah'ts possible.

Code: Select all

function rockdestroyer()
	local s = pedestal_1.surface
	for _,e in s:contents() do
		if e.go.name == "rock" then
			e.go:destroy()

EDIT: I solved it by placing an invisible surface that accepts and destroys the rocks while getting rid of the pressure plates and teleports.
Last edited by Pompidom on Fri Oct 19, 2018 3:16 pm, edited 3 times in total.
User avatar
Zo Kath Ra
Posts: 937
Joined: Sat Apr 21, 2012 9:57 am
Location: Germany

Re: Ask a simple question, get a simple answer

Post by Zo Kath Ra »

Isaac wrote: Thu Oct 18, 2018 9:56 am name = [[A356_55AC49292CB0]],
I have no idea what you're doing here :?
Post Reply