Page 1 of 1

Hiding particle effects of invisible/stealthed creatures

Posted: Mon Feb 28, 2011 5:40 pm
by yufra
The problem: particle effects give away the position of things that the player cannot see.

The setting: boss level of the necromancer pride. I enter the level in LOS of the boss, fight him for a few turns and then teleport away. I am in the process of clearing out the corner I landed into when I see some bone shield particle effects turn the corner at my back. I was expecting the boss to find me soon, but I will admit the warning the particle effects gave me severly undercut the tension.

So I started digging to understand how all of this work. It looks like the NPC's tile goes invisible in the engine.Map:updateMap call:

Code: Select all

		if a then
			-- Handles invisibility and telepathy and other such things
			if not self.actor_player or self.actor_player:canSee(a) then
				a:getMapObjects(self.tiles, mos, 10)
				a:setupMinimapInfo(a._mo, self)
			end
		end
...
	-- Cache the map objects in the C map
	self._map:setGrid(x, y, mos)
Alright, easy enough... the mo or map object of the actor is either added or not added to that tile's list of map objects to display. Particles are separately displayed in engine.Map:displayParticles:

Code: Select all

function _M:displayParticles(nb_keyframes)
...
		if nb_keyframes == 0 and e.x and e.y then
			-- Just display it, not updating, no emitting
			if e.x + e.radius >= self.mx and e.x - e.radius < self.mx + self.viewport.mwidth and e.y + e.radius >= self.my and e.y - e.radius < self.my + self.viewport.mheight then
				e.ps:toScreen(self.display_x + (adx + e.x - self.mx + 0.5) * self.tile_w * self.zoom, self.display_y + (ady + e.y - self.my + 0.5) * self.tile_h * self.zoom, self.seens(e.x, e.y), e.zoom * self.zoom)
			end
		elseif e.x and e.y then
			alive = e.ps:isAlive()

			-- Update more, if needed
			if alive and e.x + e.radius >= self.mx and e.x - e.radius < self.mx + self.viewport.mwidth and e.y + e.radius >= self.my and e.y - e.radius < self.my + self.viewport.mheight then
				e.ps:toScreen(self.display_x + (adx + e.x - self.mx + 0.5) * self.tile_w * self.zoom, self.display_y + (ady + e.y - self.my + 0.5) * self.tile_h * self.zoom, self.seens(e.x, e.y))
			end

			if not alive then
				del[#del+1] = e
				e.dead = true
			end
		else
			del[#del+1] = e
			e.dead = true
		end
...
My understanding of particles is fairly low, but my first read through says there is a concept of a particle effect being alive or dead, and that the e.ps:toScreen call is what adds the particle effect to the map. Not sure if it move the effect or if a toScreen call is required even if a particle's source didn't move... I think the latter.

How then are particles attached to actors handled? Well they are added to the actor's __particles table, which is then used by engine.Actor:move:

Code: Select all

	-- Update particle emitters attached to that actor
	local del = {}
	for e, _ in pairs(self.__particles) do
		if e.dead then del[#del+1] = e
		else
			e.x = x
			e.y = y
			map.particles[e] = true
			-- Give it our main _mo for display coords
			e._mo = self._mo
		end
	end
	for i = 1, #del do self.__particles[del[i]] = nil end
So when the actor moves the particle's position is updated. I think the fix would be to have the "e" particle object carry around a source_actor variable, and then in displayParticles check if the player can see the source_actor and if not do not display the particle effect. I don't have a lot of time to code and test it now, though, so getting it down for others to look at.

Re: Hiding particle effects of invisible/stealthed creatures

Posted: Mon Feb 28, 2011 5:50 pm
by darkgod
My long term plan is to have the possibility to attack particles to mapObjects, this way if the mo is nto shown the particles wont be, automatically, that's on my .. long .. todo list ;)

Re: Hiding particle effects of invisible/stealthed creatures

Posted: Mon Feb 28, 2011 6:14 pm
by yufra
Gotcha, that makes plenty of sense and I understand long to-do lists. :wink:

Re: Hiding particle effects of invisible/stealthed creatures

Posted: Mon Feb 28, 2011 6:21 pm
by edge2054
Another way of looking at this...

Should invisibility hide particles? There's already a penalty to attack (I believe) if you can't see your target and I'm assuming this includes invisibility and stealth.

If the conclusion is that particles should give away stealth and invisibility then things will need to be created equal between the player and the monsters somehow (maybe something similar to light giving away your location could be done).

Also I think it creates some fun design choices. Look at the Greater Mummy Lord (no particles that I know of and pretty much THE invis bad guy) or the boss of the jewelry quest (high invis but gloom so observant players can track his location).

It also opens up some possible spell effects like Faerie Fire (a nova that applies defense penalties and 'negates' stealth and invis by putting a particle effect on every actor in it's radius), Dust Storms, or whatever (Sand Breath would be a good contender now for this type of effect, put a short duration particle on affected targets). Maybe even a spell or item that specifically hides particles could be done.