Page 302 of 400

Re: Ask a simple question, get a simple answer

Posted: Sat Apr 13, 2019 8:05 am
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

Re: Ask a simple question, get a simple answer

Posted: Sat Apr 13, 2019 12:56 pm
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();
}

Re: Ask a simple question, get a simple answer

Posted: Sat Apr 13, 2019 1:10 pm
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 ?

Re: Ask a simple question, get a simple answer

Posted: Sat Apr 13, 2019 5:00 pm
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

Re: Ask a simple question, get a simple answer

Posted: Mon Apr 15, 2019 2:19 am
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

Re: Ask a simple question, get a simple answer

Posted: Mon Apr 15, 2019 11:15 pm
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

Re: Ask a simple question, get a simple answer

Posted: Tue Apr 16, 2019 1:49 am
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?

Re: Ask a simple question, get a simple answer

Posted: Tue Apr 16, 2019 2:40 am
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.

Re: Ask a simple question, get a simple answer

Posted: Tue Apr 16, 2019 2:58 am
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.

Re: Ask a simple question, get a simple answer

Posted: Tue Apr 16, 2019 3:12 am
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.