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
vanblam
Posts: 243
Joined: Sun Nov 09, 2014 12:15 am

Re: Ask a simple question, get a simple answer

Post by vanblam »

The other thing is this project I'm working on is a resource pack. So I wont have any levels at all. So I would rather have something that's already set up. The other idea I was thinking of is to just have an interior model inside the stem a little behind the main surface, then just sink in the areas I want to have a glow. That way I could have a material on that inner stem that could have a rotating texture. The only problem with that is more polys :P
Marskilla
Posts: 16
Joined: Sun Mar 17, 2019 9:08 pm

Re: Ask a simple question, get a simple answer

Post by Marskilla »

vanblam wrote: Sat Apr 13, 2019 6:59 am(...)
Image
(...)
Wow. :o

Here is another question : is there a way to enumerate objects of the same kind ?

something like

for int i=0; i<10; i++
{
door_"i".open();
}
kelly1111
Posts: 349
Joined: Sun Jan 20, 2013 6:28 pm

Re: Ask a simple question, get a simple answer

Post by kelly1111 »

vanblam wrote: Sat Apr 13, 2019 7:15 am Here is a more clear shot. I don't know, do you guys think these might look cooler with a fluctuating emissive?
Image
Tripping balls, cosmic connectors :)
I am curious as to where this will lead. These shrooms can be used indoors also ?
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 »

Marskilla wrote: Sat Apr 13, 2019 12:56 pm ...is there a way to enumerate objects of the same kind ?
Objects of the same kind typically have the same object name, and components. These work for isolating them from everything else; (mostly just the names). Sets of objects can be given specific IDs as well; this can differentiate one or more [otherwise common] items from the rest.

The iterator functions are map.allEntities() and map.entitiesAt(x,y).

So to find all doors, you could search objects whose name or ID* contains 'door', or search for objects with a door component—not all of these are, or appear as doors in the game; but this works well for detecting monsters, with a monster component.

*Id strings for automatically spawned objects will be numeric, and not helpful; this only works well with hand placed objects.

One can also [repeatedly] use the global function findEntity() with string concatenation, to find matching entities one by one.

To your example:
for int i=0; i<10; i++
{
door_"i".open();
}
It would work like this:

Code: Select all

for i = 1, 10 do
	local target = findEntity("door_"..i)  		--can be nil
	if target ~= nil and target.door ~= nil then 	--check exist, and has door component
		target.door:open()
	end
end
--this checks every object in the game, but does not check inside containers, surfaces, or in champion & monster inventories.
An example of using the iterator:

Code: Select all

function openDoors()
	local level = 1
	local map = Dungeon.getMap(level) 
	if map ~= nil then
		for obj in map:allEntities() do
			if obj ~= nil and obj.door ~= nil then
				obj.door:open()
			end
		end
	  else print("map "..level.." doesn't exist")	
	end	
end
_______________

So it is possible to animate emissiveMaps in materials, using the onUpdate hook. 8-)

Image

https://vimeo.com/330293832
User avatar
vanblam
Posts: 243
Joined: Sun Nov 09, 2014 12:15 am

Re: Ask a simple question, get a simple answer

Post by vanblam »

I like what you did there Isaac but I decided to just do the extra work and design it this way.
Image

Video here.
https://www.youtube.com/watch?v=Eu7FOeRSnWc


EDIT: I did like the way this came out but, if I try to design more mushrooms using this style the poly count would be ridiculous. So I re-designed it again using these spores that attach to the stem. This way its easier to have an lod0 and lod1 for the main part of the mushroom. The spores will not have to lod out because they're already low poly :)

Image
User avatar
vanblam
Posts: 243
Joined: Sun Nov 09, 2014 12:15 am

Re: Ask a simple question, get a simple answer

Post by vanblam »

minmay wrote: Sat Apr 13, 2019 5:39 am Remember, minimalSaveState objects only save their name, id, level, x, y, facing, and elevation, they don't store any data about the components. So when they are spawned again upon loading, they create all their components again based on the definition, and all those components will run their onInit hooks again.
I would strongly recommend you make your autoDecoEdgeCave and autoDecoFloorDetailAll functions destroy the object when they're done. Even without this issue, there's no reason to keep the base_cave_ground, base_cave_wall, etc. objects around when they no longer do anything useful.
I think the auto building base script still runs every time on load. I'll save the game and load, on that load everything seems to be fine, but when I save and reload again the objects I had auto removed come back. On my stairs down and stairs up I have them removing the pillars and ground slope objects. But the onInit only runs once on the stairs right?

Stairs up
SpoilerShow

Code: Select all

defineObject{
	name = "rc_stairs_up",
	baseObject = "base_stairs_up",
	components = {
		{
			class = "Model",
			model = "mod_assets/stotp_models/red_cave/env/rc_stairs_up.fbx",
			staticShadow = true,
		},
		{
			class = "Null",
			onInit = function(self)
				local x = self.go.x
				local y = self.go.y
				local facing = self.go.facing
				local level = self.go.level
				
				local fx,fy = getForward(facing)
				local rx,ry = getForward((facing+1)%4)

				do				
					local x = self.go.x + fx
					local y = self.go.y + fy
					if x >= 0 and y >= 0 and x < 32 and y < 32 then
						self.go.map:setAutomapTile(x, y, 4)	-- rocky wall
					end
				end

				-- destroy all pillars and slopes
				for yy=0,2 do
					for xx=-1,1 do
						local x = x + rx * xx + fx * yy
						local y = y + ry * xx + fy * yy
						if x >= 0 and y >= 0 and x < 32 and y < 32 then
							for e in self.go.map:entitiesAt(x, y) do
								if e.name == "rc_pillar_01a" 
								or e.name == "rc_pillar_01b" 
								or e.name == "rc_pillar_02a"
								or e.name == "rc_wall_slope"								
								then e:destroy()
								end
							end
						end
					end
				end
			end,
		},
	},
	tags = { "shadowgate", "red cave", "vanblam" },
}
Stairs Down
SpoilerShow

Code: Select all

defineObject{
	name = "rc_stairs_down",
	baseObject = "base_stairs_down",
	components = {
		{
			class = "Model",
			model = "mod_assets/stotp_models/red_cave/env/rc_stairs_down.fbx",
			staticShadow = true,
		},
		{
			class = "Null",
			onInit = function(self)
				local x = self.go.x
				local y = self.go.y
				local facing = self.go.facing
				local level = self.go.level
				
				local fx,fy = getForward(facing)
				local rx,ry = getForward((facing+1)%4)

				do				
					local x = self.go.x + fx
					local y = self.go.y + fy
					if x >= 0 and y >= 0 and x < 32 and y < 32 then
						self.go.map:setAutomapTile(x, y, 4)	-- rocky wall
					end
				end

				-- destroy all pillars and slopes
				for yy=0,2 do
					for xx=-1,1 do
						local x = x + rx * xx + fx * yy
						local y = y + ry * xx + fy * yy
						if x >= 0 and y >= 0 and x < 32 and y < 32 then
							for e in self.go.map:entitiesAt(x, y) do
								if e.name == "rc_pillar_01a" 
								or e.name == "rc_pillar_01b" 
								or e.name == "rc_pillar_02a"
								or e.name == "rc_wall_slope"								
								then e:destroy()
								end
							end
						end
					end
				end
			end,
		},
	},
	tags = { "shadowgate", "red cave", "vanblam" },
}
On this did I destroy the "base_cave_wall" and "base_cave_ground" correctly?
SpoilerShow

Code: Select all

do
local autoDecoEdgeCave = function(self)
local g = self.go
local supports = {
		rc_edge_support_01=true,
		rc_edge_support_02=true,
		rc_edge_support_03=true,
		rc_edge_support_04=true,
		rc_edge_support_01b=true,
		rc_edge_support_02b=true,
		rc_edge_support_03b=true,
		rc_edge_support_04b=true,
	}	
local rocks = {
		rc_rocks_trim_01=true,
		rc_rocks_trim_02=true,
		rc_rocks_trim_03=true,
		rc_wall_slope=true,
	}
		if g.map:getElevation(g.x,g.y) == g.elevation then
			local choice = math.random()
			if choice >= 0.85 then
				g:spawn("rc_edge_support_01")
			elseif choice >= 0.7 then
				g:spawn("rc_edge_support_02")
			elseif choice >= 0.55 then
				g:spawn("rc_edge_support_03")
			elseif choice >= 0.4 then
				g:spawn("rc_edge_support_04")
			end
		end
		if g.map:getElevation(g.x,g.y) == g.elevation then
			local choice = math.random()
			if choice >= 0.85 then
				g:spawn("rc_edge_support_01b")
			elseif choice >= 0.7 then
				g:spawn("rc_edge_support_02b")
			elseif choice >= 0.55 then
				g:spawn("rc_edge_support_03b")
			elseif choice >= 0.4 then
				g:spawn("rc_edge_support_04b")
			end
		end
		if g.map:getElevation(g.x,g.y) == g.elevation then
			local choice = math.random()
			if choice >= 0.8 then
				g:spawn("rc_rocks_trim_01")
			elseif choice >= 0.6 then
				g:spawn("rc_rocks_trim_02")
			elseif choice >= 0.4 then
				g:spawn("rc_rocks_trim_03")
			else
				g:spawn("rc_wall_slope",g.level,g.x,g.y,math.random(0,3),g.elevation)
			end
		end
	if g.name == "base_cave_wall" then
	g:destroy()
	end	
end	

local autoDecoFloorDetailAll = function(self)
	local g = self.go
local grass = {
		rc_grass_01a=true,
		rc_grass_01b=true,
		rc_grass_01c=true,
	}
local tiles = {
		rc_ground_tiles_01=true,
		rc_ground_tiles_02=true,
		rc_ground_tiles_03=true,
		rc_ground_tiles_04=true,
		rc_ground_tiles_05=true,
	}
local pebbles = {
		rc_ground_pebbles_01=true,
		rc_ground_pebbles_02=true,
		rc_ground_pebbles_03=true,
		rc_ground_pebbles_04=true,
	}		
	local choice = math.random()
	local choice2 = math.random()
	local choice3 = math.random()
	
	if choice >= 0.6 then
	  spawn("rc_grass_01a",g.level,g.x,g.y,math.random(0,3),g.elevation)
	elseif choice >= 0.4 then
	  spawn("rc_grass_01b",g.level,g.x,g.y,math.random(0,3),g.elevation)
	elseif choice >= 0.2 then
	  spawn("rc_grass_01c",g.level,g.x,g.y,math.random(0,3),g.elevation)
end
	if choice2 >= 0.94 then
	  spawn("rc_ground_tiles_01",g.level,g.x,g.y,math.random(0,3),g.elevation)
	elseif choice2 >= 0.88 then
	  spawn("rc_ground_tiles_02",g.level,g.x,g.y,math.random(0,3),g.elevation)
	elseif choice2 >= 0.82 then
	  spawn("rc_ground_tiles_03",g.level,g.x,g.y,math.random(0,3),g.elevation)
	elseif choice2 >= 0.76 then
	  spawn("rc_ground_tiles_04",g.level,g.x,g.y,math.random(0,3),g.elevation)
	elseif choice2 >= 0.7 then
	  spawn("rc_ground_tiles_05",g.level,g.x,g.y,math.random(0,3),g.elevation)
end
	if choice3 >= 0.8 then
	  spawn("rc_ground_pebbles_04",g.level,g.x,g.y,math.random(0,3),g.elevation)
	elseif choice3 >= 0.6 then
	  spawn("rc_ground_pebbles_01",g.level,g.x,g.y,math.random(0,3),g.elevation)
	elseif choice3 >= 0.4 then
	  spawn("rc_ground_pebbles_02",g.level,g.x,g.y,math.random(0,3),g.elevation)
	elseif choice3 >= 0.2 then
	  spawn("rc_ground_pebbles_03",g.level,g.x,g.y,math.random(0,3),g.elevation)
end

	if g.name == "base_cave_ground" then
	g:destroy()
	end	
	
end
defineObject{
	name = "base_cave_wall",
	baseObject = "base_wall",
	components = {
		{
			class = "Null",
			onInit = autoDecoEdgeCave,
		},
	},
}

defineObject{
	name = "base_cave_ground",
	baseObject = "base_floor",
	components = {
		{
			class = "Null",
			onInit = autoDecoFloorDetailAll,
		},
	},
}
end
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 »

vanblam wrote: Mon Apr 15, 2019 2:19 am I did like the way this came out but, if I try to design more mushrooms using this style the poly count would be ridiculous. So I re-designed it again using these spores that attach to the stem. This way its easier to have an lod0 and lod1 for the main part of the mushroom. The spores will not have to lod out because they're already low poly :)
Are you doing high-poly baked normal maps?
User avatar
vanblam
Posts: 243
Joined: Sun Nov 09, 2014 12:15 am

Re: Ask a simple question, get a simple answer

Post by vanblam »

Isaac wrote: Tue Apr 16, 2019 1:49 am
vanblam wrote: Mon Apr 15, 2019 2:19 am I did like the way this came out but, if I try to design more mushrooms using this style the poly count would be ridiculous. So I re-designed it again using these spores that attach to the stem. This way its easier to have an lod0 and lod1 for the main part of the mushroom. The spores will not have to lod out because they're already low poly :)
Are you doing high-poly baked normal maps?
No just using the basic blender surface normals and I use Quixel Suite 2 for texture normals.

But when I designed the veins coming up the edges I had to create more faces just make it look right. It was around 1100 faces. The set up I have now its down to 650 for lod0 and 300 for lod1.
minmay
Posts: 2780
Joined: Mon Sep 23, 2013 2:24 am

Re: Ask a simple question, get a simple answer

Post by minmay »

1,100 tris per mushroom would be fine honestly. The lod1_mesh for a forest oak is 718 tris and has the added overhead of rigged animation and a double-sided material.
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
vanblam
Posts: 243
Joined: Sun Nov 09, 2014 12:15 am

Re: Ask a simple question, get a simple answer

Post by vanblam »

minmay wrote: Tue Apr 16, 2019 2:58 am 1,100 tris per mushroom would be fine honestly. The lod1_mesh for a forest oak is 718 tris and has the added overhead of rigged animation and a double-sided material.
True..To be honest it was also a pain to manipulate the shape of the stem to create other mushrooms that look different without designing a new stem from scratch, on top of that I had to do a lot more texture work to make the seams not as visible. The new style still looks nice and I'm able to pump out other mushrooms quicker, plus the texture work is easier (I'm lazy lol) :).

_____________________

Is there a way to have particle effects disappear at a certain distance from the player?

_____________________

How do I add a part to this that will tell it not to spawn if there is a particular object in a 3x3 area?

Code: Select all

if g.map:getElevation(g.x,g.y) == g.elevation then
			local choice = math.random()
			if choice >= 0.85 then
				g:spawn("rc_edge_support_01")
			elseif choice >= 0.7 then
				g:spawn("rc_edge_support_02")
			elseif choice >= 0.55 then
				g:spawn("rc_edge_support_03")
			elseif choice >= 0.4 then
				g:spawn("rc_edge_support_04")
			end
		end
Sorry for all the questions lol. I'm just frustrated on my loading issues.
Post Reply