Page 1 of 2

Crushing monsters by closing door

Posted: Thu Sep 13, 2012 9:47 pm
by JKos
Has anybody else tried to implement this yet?
I can't find an easy way to make this work nicely.

I think we need door:onClose hook and monster:movingDirection-method or property, then I could implement script which finds monsters moving through door when it is closing and does damage to them.
As a programmer I think those should be pretty easy to implement, just call door:onClose from door:close-method and there has to be moving direction calculation code already, because it is passed to monster:onMove-hook.
So Almost Humans, could you please implement these? ;)

Or maybe someone smarter than me has figured out how to do this with current features?

Re: Crushing monsters by closing door

Posted: Tue Sep 18, 2012 10:43 pm
by JKos
I was able to implement this after patch 1.2.8. I't not very nice solution, but works.

This example shows how you can make bashable spiders.
First you need to override the spider asset in init.lua (or in other lua file)

Code: Select all

cloneObject{
	name = "spider",
	baseObject = "spider",
	onMove = function(self, dir)
	   monsters.directions[self.id] = dir
	end,
	onAttack = function(self, attack)
	   monsters.directions[self.id] = self.facing
	end,	
	onDamage = function(self, attack)
	   -- to prevent continuous bashing with door
	   monsters.directions[self.id] = nil
	end,
}
Then you have to add a script entity named monsters and define table-property named directions there.

Code: Select all

directions = {}
monsters moving directions are stored there as you can see from previous code.

Then make another script entity named doors

Code: Select all

function close(door_name)

-- do some damage to monsters at same tile as the door and moving through it
	local door = findEntity(door_name)
	local monstersAtDoor = entitiesAt(door.level,door.x,door.y)
	
	for monst in monstersAtDoor do
		if door.facing == monsters.directions[monst.id] then
			damageTile(door.level,door.x,door.y,door.facing,1,"physical",5)
			print("door made damage to "..monst.id)
		end
	end

-- do some damage to monsters at other side of the door and moving through it	
	local door_x = door.x
	local door_y = door.y
	
	if (door.facing == 0) then
		door_y = door_y + 1
	elseif (door.facing == 2) then
		door_y = door_y - 1 
	elseif (door.facing == 1) then
		door_x = door_x + 1 	
	else
		door_x = door_x - 1 
	end	
	
	local monstersAtOtherSideOfDoor = entitiesAt(door.level,door_x,door_y)	
	if door.facing >= 2 then
	  door_opposite_facing = door.facing - 2
	else
	  door_opposite_facing = door.facing + 2
	end
	
	for monst in monstersAtOtherSideOfDoor do
	print("monter_found:"..monst.id)
		if door_opposite_facing == monsters.directions[monst.id] then
			damageTile(door.level,door_x,door_y,door_opposite_facing,1,"physical",5)
			print("door made damage to " ..monst.id)
		end
	end	
	
	door:close()
		
end

function toggle(door_name)
	local door = findEntity(door_name)
	if door:isOpen() then 
		self.close(door_name)
	else
		door:open()
	end
end

-- you have to make similar function for every door, if you want it to be able to deal damage to monsters :(
-- I wish there was door:onClose-hook or possibility to pass parameters to actions called by connectors
function toggleMetal1()
 self.toggle("dungeon_door_metal_1")
end
add dungeon_door_metal_1 and a wall button which triggers doors.toggleMetal1()

Spiders will receive damage when moving or attacking through dungeon_door_metal_1
Have fun crushing those nasty spiders :)

Re: Crushing monsters by closing door

Posted: Wed Sep 19, 2012 7:23 am
by petri
Neat! I'll add onOpen and onClose hooks for you in the next patch. Any other hooks that would be useful?

Re: Crushing monsters by closing door

Posted: Wed Sep 19, 2012 11:05 am
by Montis
maybe onTeleport for teleporters? that would actually be really neat like you could teleport and instantly deactivate the teleporter "behind" you.

what I also would like to see is:
Teleporter:isActivated()
Timer:isActivated()
-> returns true or false if the teleporter or timer is activated/deactivated (for a timer that would mean: currently running).

Re: Crushing monsters by closing door

Posted: Wed Sep 19, 2012 8:29 pm
by JKos
Cool, thanks so much for adding that hook. Now it works like a charm. Here is an example how to make spiders and snails crushable by wooden and metal doors.


init.lua

Code: Select all


local MonstersList = {"crab","crowern","cube","snail","spider"}


for i=1,# MonstersList do 
	cloneObject{
		name = MonstersList[i],
		baseObject = MonstersList[i],
		onMove = function(self, dir)
			monsters.directions[self.id] = dir
		end,
		onAttack = function(self, attack)
			   monsters.directions[self.id] = self.facing
		end,
		onDamage = function(self, attack)
			-- to prevent continuous bashing with door
			 monsters.directions[self.id] = nil
		end,
		onDie = function(self)
		    -- clear dead monsters from directions table
			monsters.directions[self.id] = nil
		end,		
	}
end


cloneObject{
	name = "dungeon_door_metal",
	baseObject = "dungeon_door_metal",
	onClose = function(self)
		doors.crush(self,30)
	end,
}
cloneObject{
	name = "dungeon_door_wooden",
	baseObject = "dungeon_door_wooden",
	onClose = function(self)
		doors.crush(self,10)
	end,
}

monsters script-entity

Code: Select all

directions = {}
doors script-entity

Code: Select all

debug = false 

function crush(door, damagePower)
-- do some damage to monsters on same tile as the door and moving through it
	local monstersAtDoor = entitiesAt(door.level,door.x,door.y)
	
	for monst in monstersAtDoor do
		if door.facing == monsters.directions[monst.id] then
			damageTile(door.level,door.x,door.y,door.facing,1,"physical",damagePower)
			if self.debug then print("door made damage to "..monst.id) end
		end
	end

-- do some damage to monsters at other side of the door and moving through it	
	local door_x = door.x
	local door_y = door.y
	-- find a tile which is next to door to it's facing direction
	if (door.facing == 0) then
		door_y = door_y - 1
	elseif (door.facing == 2) then
		door_y = door_y + 1 
	elseif (door.facing == 1) then
		door_x = door_x + 1 	
	else
		door_x = door_x - 1 
	end	
    
	if door.facing >= 2 then
	  door_opposite_facing = door.facing - 2
	else
	  door_opposite_facing = door.facing + 2
	end
	
	local monstersAtOtherSideOfDoor = entitiesAt(door.level,door_x,door_y)	

	for monst in monstersAtOtherSideOfDoor do
		if door_opposite_facing == monsters.directions[monst.id] then
			damageTile(door.level,door_x,door_y,door_opposite_facing,1,"physical",damagePower)
			if self.debug then print("door made damage to " ..monst.id) end
		end
	end	
end
So now dungeon_door_metal and dungeon_door_wooden will deal damage to snails and spiders when they are moving or attacking through door when it's closing.
Metal door will make more damage than wooden door.

Re: Crushing monsters by closing door

Posted: Wed Sep 19, 2012 8:57 pm
by JKos
I uploded a sample dungeon with damage dealing doors to my google-drive.

https://docs.google.com/open?id=0B7cR7s ... FFtWWJQcWs
just unzip it to your Documents\Almost Human\Legend of Grimrock\Dungeons
and open it with editor

Any feedback is welcome. And I hope to see this used in some mods too :) I'm better at writing scripts than designing dungeons.

Re: Crushing monsters by closing door

Posted: Wed Sep 19, 2012 9:16 pm
by petri
Great! One thing still, I think it would be better to remove dead monsters from monsters.directions. As it is now the table gets bigger and bigger when new monsters are spawned which consumes memory and makes save games larger.

Re: Crushing monsters by closing door

Posted: Wed Sep 19, 2012 9:56 pm
by JKos
petri wrote:Great! One thing still, I think it would be better to remove dead monsters from monsters.directions. As it is now the table gets bigger and bigger when new monsters are spawned which consumes memory and makes save games larger.
Thanks, it's really nice to get feedback from you. But I think they are removed already because they are set to nil on onDamage-hook, which is of course always called just before onDie-hook. So I have accidentally implemented that already :) I just tested it.

Re: Crushing monsters by closing door

Posted: Thu Sep 20, 2012 7:12 am
by petri
Ah, ok, I missed that. OnDamage should cover all common cases. There might be some corner cases where monster is killed without being damaged. For instance telefragging.

Re: Crushing monsters by closing door

Posted: Thu Sep 20, 2012 11:14 am
by Darklord
Hah this is awesome, I kinda of missed hitting enemies with doors! :lol:

Daniel.