[Bug?] MonsterGroup & damageTile

Talk about creating Grimrock 1 levels and mods here. Warning: forum contains spoilers!
Post Reply
Zraak
Posts: 4
Joined: Tue May 14, 2013 8:08 pm

[Bug?] MonsterGroup & damageTile

Post by Zraak »

Greetings to you all, for this is my first Post here.

I have been fiddling with a problem that is caused by "MonsterGroup" and "damageTile".

For my little mod I wish to create a trap that kills everything that steps on it. The trap is a bundle of spears that come out of a wall. Once outside they block the party and monsters until a reset. By now it works well with the party and single monsters. But when a MonsterGroup triggers it, only one Monster of the group dies and the others continue walking through it. I used damageTile to kill the monster or the party.
Why does damageTile only kill one monster?

Apparently there is only one monster in the cell when the group walks into it and triggers the trap. I got this when I tried checking for all the monsters in the cell. If I start looking for monsters in a radius of one cell around the trap (all 9 cells) I definitely find all that belong to that group, but I also get all other monsters as well.

How do I find only those that belong to a group altogether? Is there a way to do this by code?

One attempt was to spawn a timer to cause damage on the cell very rapidly with damageTile. It worked on killing the monsters but it crashed the animation of the trap (the spears are doors that open and close) and spawn of the blockage.

My current approach on this issue would be to create copies of the same Monster, name it differently, group it and never use the group on a level more than once. That way I could ":destroy()" them without any crashes. This is a workaround but a very ugly one. Is there a better way to do this?

Here you can see the arrangement of the trap.
Image
User avatar
Komag
Posts: 3659
Joined: Sat Jul 28, 2012 4:55 pm
Location: Boston, USA

Re: [Bug?] MonsterGroup & damageTile

Post by Komag »

If I were you I would probably try to explore the timer route more and see why it's causing a crash, that seems the best solution if you can get it to work.

Very cool trap and wallset! :D
Finished Dungeons - complete mods to play
User avatar
JKos
Posts: 464
Joined: Wed Sep 12, 2012 10:03 pm
Location: Finland
Contact:

Re: [Bug?] MonsterGroup & damageTile

Post by JKos »

Simple for-loop should work:

Code: Select all

for i=0,3 do 
  damageTile(...)
end
Edit: Actually it doesn't, I read your post too hastily, sorry.
- LoG Framework 2http://sites.google.com/site/jkoslog2 Define hooks in runtime by entity.name or entity.id + multiple hooks support.
- cloneObject viewtopic.php?f=22&t=8450
Zraak
Posts: 4
Joined: Tue May 14, 2013 8:08 pm

Re: [Bug?] MonsterGroup & damageTile

Post by Zraak »

Thank you Komag, your hunch was right, I got it worked out with the timer somehow. But I couldn't use damageTile to make it work. Please look at the code section to see why. I know there are lots of ways to improve the code, but I am happy so far that it works. :D

Code: Select all

-- This script Name: trapScript
--[[
	This function kills the party if it is in the cell or spawns a blockage 
	and creates the setup for killing mosnters if there were any.
	It is called by the Spears-"Door" with a onOpen hook.
--]]
function stab(self)
	local block = nil
	for val in entitiesAt(self.level,self.x,self.y) do
		if (val.class == "Blockage") then
				block = val
			break
		end			
	end
	
	local onself = 0
	for val in entitiesAt(self.level,self.x,self.y) do
		if (val.class == "Party" ) then
			onself = 1
			break
		elseif (val.class == "Monster" ) then
			onself = 2
			break
		end			
	end
	
	if (onself == 1) then
		damageTile(self.level, self.x, self.y, self.facing, 6, "physical", 5000)
	elseif (onself == 2) then
		spawn("timer", self.level, self.x, self.y, self.facing) -- timer to run the script repeatedly
			:addConnector("activate", "trapScript", "destroyMonsterGroup")
			:setTimerInterval(0.01)
			:activate()			
		spawn("counter", self.level, self.x, self.y, self.facing) -- counter to limit run to 4 times
			:setValue(0)
	end		
	
	if (block == nil)and(onself ~= 1) then
		spawn("bc_block_invis_resilient", self.level, self.x, self.y, self.facing)
	end
		
	if (onself == 1)then
		spawn("fx", self.level, self.x, self.y, self.facing):setParticleSystem("death_dust")	
		party:playScreenEffect("party_crush")
	end
	

end


--[[
	This function deletes all monsters that step on the field. I had to destroy 
	the monsters because dealing damage with damageTile caused los in performance 
	and wrecked the animation of the doors, plus it caused the blockage hit sound 
	to trigger each time. It also gives some exp to the player, however if it were 
	possible to get the exp value out of the monster it could be the exact ammount.
	So now it is just some fixed value.
--]]
function destroyMonsterGroup(self)
	local count = nil
	for val in entitiesAt(self.level,self.x,self.y) do
		if (val.class == "Counter") then
			count = val
			break
		end			
	end	
	
	if (count:getValue() < 4) then
		count:increment()
		for val in entitiesAt(self.level,self.x,self.y) do
			if (val.class == "Monster" ) then
				val:destroy()				
			end			
		end
	else
		spawn("fx", self.level, self.x, self.y, self.facing):setParticleSystem("bc_monster_death")
		for i=1,4 do		
			if ( party:getChampion(i):getEnabled() ) then
				party:getChampion(i):gainExp(50)
			end
		end
		count:destroy()
		self:destroy()
	end	
end


--[[
	This function opens the path and respawns the pressure plate if there is any.
	It is called by the Spears-"Door" with a onClose hook.
--]]
function clear(self)
	local block = nil
	for val in entitiesAt(self.level,self.x,self.y) do
		if (val.class == "Blockage") then
				val:destroy()
			break
		end			
	end
	
	local plate = false
	for val in entitiesAt(self.level,self.x,self.y) do
		if (val.class == "PressurePlate") then
			val:destroy()
		
			local doors = {}
			
			for val in entitiesAt(self.level,self.x,self.y) do
				if (val.name == "bc_wall_trap_spear_s01") or   --had to call val by names, calling val by class caused always nil don't know why though
				   (val.name == "bc_wall_trap_spear_s01_deco") or
		 		   (val.name == "bc_wall_trap_spear_s02") or
				   (val.name == "bc_wall_trap_spear_s02_deco") then
					table.insert(doors,val)
				end	
			end
			
			local plate = spawn("bc_pressure_plate", self.level, self.x, self.y, self.facing)
								:setTriggeredByParty(true)
								:setTriggeredByMonster(true)
								:setTriggeredByItem(false)
								:setActivateOnce(true)
								:setSilent(false)			
			for i, val in pairs(doors) do
				plate:addConnector("activate", val.id, "toggle")
			end			

			break
		end			
	end
end
User avatar
Komag
Posts: 3659
Joined: Sat Jul 28, 2012 4:55 pm
Location: Boston, USA

Re: [Bug?] MonsterGroup & damageTile

Post by Komag »

with just a brief skim it looks good to me, glad you got it working, very cool :)

you're definitely not a newbie with Lua and viariables 8-)
Finished Dungeons - complete mods to play
Zraak
Posts: 4
Joined: Tue May 14, 2013 8:08 pm

Re: [Bug?] MonsterGroup & damageTile

Post by Zraak »

Thank you for the honor. Truth to be told. This is my first time with lua and I have battling it for like 7 weeks now.
User avatar
Drakkan
Posts: 1318
Joined: Mon Dec 31, 2012 12:25 am

Re: [Bug?] MonsterGroup & damageTile

Post by Drakkan »

interesting wallset there. Will it be released for public use ? :)
Breath from the unpromising waters.
Eye of the Atlantis
Post Reply