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
Isaac
Posts: 3185
Joined: Fri Mar 02, 2012 10:02 pm

Re: Ask a simple question, get a simple answer

Post by Isaac »

minmay wrote: Tue Mar 05, 2019 8:45 pm
Isaac wrote: Tue Mar 05, 2019 5:17 pmFirst, my impression has been that entitiesAt is a slower function than allEntities
While a call to allEntities() alone is potentially faster than a call to entitiesAt() alone, allEntities() is way slower if you're actually using the returned iterator, because you're iterating over 1024 squares worth of entities instead of one square worth of entities. It's much better to use entitiesAt().
Thanks for that information. ;)
My original impression I think came from one of your posts years ago, but I might have forgotten the context. Perhaps it was advice for a specific usage; (which matches with what you have said above).

Do you know (or offhand guess) —for sake of example (but this is not planned)— if using allEntities instead of entitiesAt in a mod like ORRR3 would have significant impact on low-spec performance every time a spell is cast? (I assume yes, but I have not tried it to see if it's noticeable.)

I am reworking the asset to support regions, so it will change, but the version that works (this current one) used the iterator because it can't miss. In the new version, I intend to use a collected table of anti_magic tile locations (built with onInit) instead of using either entitiesAt or allEntities.
(No map changes should be necessary, just update the asset script.)

*This does mean that moving the anti-magic-tile would invalidate the address in the table, and it would have to be manually updated.
minmay
Posts: 2780
Joined: Mon Sep 23, 2013 2:24 am

Re: Ask a simple question, get a simple answer

Post by minmay »

Well, what would you intuitively expect to be faster? Iterating over all the entities on one square, or iterating over all the entities on the entire level?
Grimrock 1 dungeon
Grimrock 2 resources
I no longer answer scripting questions in private messages. Please ask in a forum topic or this Discord server.
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 »

Oh I know it will be slower, but I don't know if it will be noticeable. In this case it does not matter, it's not planned to add the thing to the mod, and the next one won't be using it. But of course other things do use it.

*But technically, I don't know how allEntities iterates; is it by tile, by name, Id. In the case of names is it alphabetically? numeric?
Last edited by Isaac on Tue Mar 05, 2019 11:48 pm, edited 1 time in total.
minmay
Posts: 2780
Joined: Mon Sep 23, 2013 2:24 am

Re: Ask a simple question, get a simple answer

Post by minmay »

Depends on the context. How many entities are on the level? How much computation are you doing for each one? You'll need to profile it in your mod to be certain.
Grimrock 1 dungeon
Grimrock 2 resources
I no longer answer scripting questions in private messages. Please ask in a forum topic or this Discord server.
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 »

Thanks. 8-)
Killcannon
Posts: 73
Joined: Sun Apr 12, 2015 2:57 pm

Re: Ask a simple question, get a simple answer

Post by Killcannon »

Still working on this puzzle thing. I got the block to fall like I want; but the next stage is to be able to reset the block either after it kills the boss or in case the player misses. I found NichG's elevator script but when I try to use it on the block, it causes the block to jerk slightly and not rise or fall. So the script is likely working, but something is preventing the block from moving. I'm thinking it's because of the interaction between the block and the pushable floor tiles it uses to guide it. Is there a way to allow the block to be 'pushed' up or down via script? I'm guessing I'll have to define that in either the floor tile or block object or both.
Pompidom
Posts: 497
Joined: Sun May 06, 2018 9:42 pm

Re: Ask a simple question, get a simple answer

Post by Pompidom »

How about you tell us exactly how you made it fall? More info first and be specific. Tell us the script.
Did you give it a gravity component? And does it simply work when the block is activated?

Resetting the block is simply done by setPosition granted after you deactivated all other shenanigans you used to get the block there in the first place. The jerking motion can be caused by a lot of things and is probably a fight between 2 conflicting setPosition scripts working at once, but it's definitely not the interaction between the block floor tile.

Use this script, It works just fine on both activated blocks as deactivated blocks.
link a timer with 0 to the script and activate the timer with a button.
Place the script at the same square as the block and on the same height. In this case on elevation 0. It will lift the block to elevation 1 in a smooth fashion and then stop at exactly elevation 1. Deactivate the timer yourself after x seconds.

Code: Select all

startHeight = 1
dir = 0
posY = 0

function block()
	
	local spinner = findEntity("pushable_block_5")
	
	if posY < startHeight then
		posY = posY + 0.002
		spinner:setPosition(script_entity_162.x, script_entity_162.y, dir, posY, script_entity_162.level)
	
	end
end
minmay
Posts: 2780
Joined: Mon Sep 23, 2013 2:24 am

Re: Ask a simple question, get a simple answer

Post by minmay »

Repositioning pushable blocks with setPosition() is not a good idea, because their DynamicObstacleComponent will continue blocking the square they were previously on. You should destroy the block and spawn a new one instead.
Grimrock 1 dungeon
Grimrock 2 resources
I no longer answer scripting questions in private messages. Please ask in a forum topic or this Discord server.
Killcannon
Posts: 73
Joined: Sun Apr 12, 2015 2:57 pm

Re: Ask a simple question, get a simple answer

Post by Killcannon »

So no problem. I've been doing some testing anyway just to figure out the problem.

I am using this script that I found here: https://www.nexusmods.com/legendofgrimrock2/mods/10

Code: Select all

function lowerPlatform()
	local y = elevator_platform:getWorldPositionY()
	local level = elevator_platform.level	
	local px = elevator_platform.x
	local py = elevator_platform.y
	local face = elevator_platform.facing
	
	elevator_ascend_timer.timer:stop() -- Lets not do both at once
	
	y = y - 0.01
	
	-- Each grid cube is 3 units high in worldspace
	-- Once we're below the 'lip' that we want the party to be able
	-- to cross, we need to change the vertical coordinate of the platform
	
	if y<-0.5 then 
		elevator_platform:setPosition(px,py,face,-1,level)
	elseif y<2.5 then
		elevator_platform:setPosition(px,py,face,0,level)
	end
	
	if y<-3 then -- Stop the elevator
		y=-3
		elevator_descend_timer.timer:stop()
	end
	
	elevator_platform:setWorldPositionY(y)
end

function raisePlatform()
	local y = elevator_platform:getWorldPositionY()
	local level = elevator_platform.level	
	local px = elevator_platform.x
	local py = elevator_platform.y
	local face = elevator_platform.facing
	
	elevator_descend_timer.timer:stop() -- Lets not do both at once
	
	y = y + 0.01
	
	-- Each grid cube is 3 units high in worldspace
	-- Once we're below the 'lip' that we want the party to be able
	-- to cross, we need to change the vertical coordinate of the platform
	
	if y>2.5 then 
		elevator_platform:setPosition(px,py,face,1,level)
	elseif y>-0.5 then
		elevator_platform:setPosition(px,py,face,0,level)
	end
	
	if y>3 then -- Stop the elevator
		y=3
		elevator_ascend_timer.timer:stop()
	end
	
	elevator_platform:setWorldPositionY(y)
	
	-- However, we also have to adjust the position of everything in this square
	-- Otherwise things will fall through the platform
	-- We might also want to adjust only things near the platform's level
	-- so that e.g. you can hide under an elevator tile.
	for obj in elevator_platform.map:entitiesAt(px,py) do
		if obj.gravity then -- Only move things that would be lifted
			if (math.abs(obj:getWorldPositionY()-y)<0.5) then
				obj:setWorldPositionY(y+0.01)
			end
		end
	end
end
I have the script connected to 2 timers one for function raisePlatform() and the other for function lowerPlatform(). Each timer is connected to it's own lever. (I'm using levers, he used a button but the effect should be the same.) The idea is you pull the lever and it starts the object moving up or down. In his example he used a Castle Bridge.

For the testing purposes, I've gone ahead and copied everything over like he had with the only exception being that I'm not using a 3 tiered level. It works, until I remove the castle bridge object and add in the movable block object and rename it. The block falls just fine due to the gravity component. (It does take 10 seconds to do so but does so.)

Code: Select all

defineObject{
	name = "falling_block",
	baseObject = "base_floor_decoration",
	components = {
		{
			class = "Model",
			model = "assets/models/env/pushable_block_01.fbx",
		},
		{
			class = "ProjectileCollider",
		},
		{
			class = "Obstacle",
			hitSound = "$weapon",
		},
		{
			class = "Gravity",
		},
		{
			class = "DynamicObstacle",
		},
		{
			class = "PushableBlock",
		},
		{
			class = "Clickable",
			name = "clickNorth",
			offset = vec(0, 1.15, 1.2),
			size = vec(1.2, 1.2, 0.1),
			maxDistance = 1,
			--debugDraw = true,
			onClick = function(self)
				if party.facing == (self.go.facing+2) % 4 then
					self.go.pushableblock:push(party.facing)
				end
			end,
		},
		{
			class = "Clickable",
			name = "clickEast",
			offset = vec(1.2, 1.15, 0),
			size = vec(0.1, 1.2, 1.2),
			maxDistance = 1,
			--debugDraw = true,
			onClick = function(self)
				if party.facing == (self.go.facing+3) % 4 then
					self.go.pushableblock:push(party.facing)
				end
			end,
		},
		{
			class = "Clickable",
			name = "clickSouth",
			offset = vec(0, 1.15, -1.2),
			size = vec(1.2, 1.2, 0.1),
			maxDistance = 1,
			--debugDraw = true,
			onClick = function(self)
				if party.facing == self.go.facing then
					self.go.pushableblock:push(party.facing)
				end
			end,
		},
		{
			class = "Clickable",
			name = "clickWest",
			offset = vec(-1.2, 1.15, 0),
			size = vec(0.1, 1.2, 1.2),
			maxDistance = 1,
			--debugDraw = true,
			onClick = function(self)
				if party.facing == (self.go.facing+1) % 4 then
					self.go.pushableblock:push(party.facing)
				end
			end,
		},
		{
			class = "Light",
			name = "lightNorth",
			offset = vec(0,1.2,1.2),
			range = 1.2,
			color = vec(5,2,2,0.3),
			brightness = 2,
			fadeOut = 0,
			fillLight = true,
		},
		{
			class = "Light",
			name = "lightEast",
			offset = vec(1.2,1.2,0),
			range = 1.2,
			color = vec(5,2,2,0.3),
			brightness = 2,
			fadeOut = 0,
			fillLight = true,
		},
		{
			class = "Light",
			name = "lightSouth",
			offset = vec(0,1.2,-1.2),
			range = 1.2,
			color = vec(5,2,2,0.3),
			brightness = 2,
			fadeOut = 0,
			fillLight = true,
		},
		{
			class = "Light",
			name = "lightWest",
			offset = vec(-1.2,1.2,0),
			range = 1.2,
			color = vec(5,2,2,0.3),
			brightness = 2,
			fadeOut = 0,
			fillLight = true,
		},		
		{
			class = "Sound",
			sound = "pushable_block_hover",
			offset = vec(0, 1.5, 0),
			enabled = false,
		},
	},
	editorIcon = 220,
}
When you hit the lever for it to go up. It jumps the first iteration of the raisePlatform() script, but is pulled immediately back down to its base default position, and never moves up. This is with or without the pushable floor tiles active or off. Which is why I was saying it probably has to do with the pushable block itself or the pushable floor tiles.

This is why I was asking if there was a way to script the block itself to move up and down. I also had concerns with what minmay pointed out with the object collider. If I can script the pushable block itself to move up or down. Then I can script a function with a button press or off the monster.die that pushes the block back up as if the player was pushing it.

edit:


Further testing. I thought it may be the gravity component itself, so I added in enabled = true to the gravity component to turn it off and on, then added to the elevator script the argument to turn off gravity ((elevator_platform.gravity:disable() )). The result of this was the same as before. So I tried this with a default pushable block. ((Here's the script for you Pompidom))

Code: Select all

defineObject{
	name = "pushable_block",
	baseObject = "base_floor_decoration",
	components = {
		{
			class = "Model",
			model = "assets/models/env/pushable_block_01.fbx",
		},
		{
			class = "ProjectileCollider",
		},
		{
			class = "Obstacle",
			hitSound = "$weapon",
		},
		{
			class = "DynamicObstacle",
		},
		{
			class = "PushableBlock",
		},
		{
			class = "Clickable",
			name = "clickNorth",
			offset = vec(0, 1.15, 1.2),
			size = vec(1.2, 1.2, 0.1),
			maxDistance = 1,
			--debugDraw = true,
			onClick = function(self)
				if party.facing == (self.go.facing+2) % 4 then
					self.go.pushableblock:push(party.facing)
				end
			end,
		},
		{
			class = "Clickable",
			name = "clickEast",
			offset = vec(1.2, 1.15, 0),
			size = vec(0.1, 1.2, 1.2),
			maxDistance = 1,
			--debugDraw = true,
			onClick = function(self)
				if party.facing == (self.go.facing+3) % 4 then
					self.go.pushableblock:push(party.facing)
				end
			end,
		},
		{
			class = "Clickable",
			name = "clickSouth",
			offset = vec(0, 1.15, -1.2),
			size = vec(1.2, 1.2, 0.1),
			maxDistance = 1,
			--debugDraw = true,
			onClick = function(self)
				if party.facing == self.go.facing then
					self.go.pushableblock:push(party.facing)
				end
			end,
		},
		{
			class = "Clickable",
			name = "clickWest",
			offset = vec(-1.2, 1.15, 0),
			size = vec(0.1, 1.2, 1.2),
			maxDistance = 1,
			--debugDraw = true,
			onClick = function(self)
				if party.facing == (self.go.facing+1) % 4 then
					self.go.pushableblock:push(party.facing)
				end
			end,
		},
		{
			class = "Light",
			name = "lightNorth",
			offset = vec(0,1.2,1.2),
			range = 1.2,
			color = vec(5,2,2,0.3),
			brightness = 2,
			fadeOut = 0,
			fillLight = true,
		},
		{
			class = "Light",
			name = "lightEast",
			offset = vec(1.2,1.2,0),
			range = 1.2,
			color = vec(5,2,2,0.3),
			brightness = 2,
			fadeOut = 0,
			fillLight = true,
		},
		{
			class = "Light",
			name = "lightSouth",
			offset = vec(0,1.2,-1.2),
			range = 1.2,
			color = vec(5,2,2,0.3),
			brightness = 2,
			fadeOut = 0,
			fillLight = true,
		},
		{
			class = "Light",
			name = "lightWest",
			offset = vec(-1.2,1.2,0),
			range = 1.2,
			color = vec(5,2,2,0.3),
			brightness = 2,
			fadeOut = 0,
			fillLight = true,
		},		
		{
			class = "Sound",
			sound = "pushable_block_hover",
			offset = vec(0, 1.5, 0),
			enabled = false,
		},
	},
	editorIcon = 220,
}
The block refuses to raise or lower at all. I will continue my testing on this.


As a side note: I did notice that the castle bridge will only raise when the height allows for the characters to move to the floor above it regardless of height setting in the script, but will seem to lower through the floor without stopping until it reaches the lower height value.
Pompidom
Posts: 497
Joined: Sun May 06, 2018 9:42 pm

Re: Ask a simple question, get a simple answer

Post by Pompidom »

minmay wrote: Wed Mar 06, 2019 10:44 am Repositioning pushable blocks with setPosition() is not a good idea, because their DynamicObstacleComponent will continue blocking the square they were previously on. You should destroy the block and spawn a new one instead.
In this case, it can actually be beneficial. An invisible obstacle left by the original location of the block will prevent the player from getting weird ideas like for example trying to walk upon the block that has dropped down. which won't work since he will then fall through the block.
Let's say the block is used to drop down from elevation 1 to elevation 0. He will have enough trouble as it is with people solving the puzzle alternatively by either jumping on the boss or glitching through blocks.
Block falls down, obstacle will prevent the player from walking/glitching through the fallen block. Block moves back up again, everything is fine since the block is back to the original position.

The script I provided works fine for what he wants to use it. Just adjust the speed and he's done.

https://youtu.be/8sLtNd--jsY
Post Reply