Detecting if the party can move

Talk about creating Grimrock 1 levels and mods here. Warning: forum contains spoilers!
Post Reply
User avatar
Diarmuid
Posts: 807
Joined: Thu Nov 22, 2012 6:59 am
Location: Montreal, Canada
Contact:

Detecting if the party can move

Post by Diarmuid »

Hi!

I was wondering if there was any reliable way to detect if the party can move towards a tile.

Right now I was using the following function:
SpoilerShow

Code: Select all

function collisionAhead(entity, direction)
	
	if not(entity) then return false end;

	local level, x, y = entity.level, entity.x, entity.y;
	local facing = direction or entity.facing;
	
	local dx, dy = getForward(facing);
	
	-- Check for solid wall
	if isWall(level, x+dx, y+dy) then
		return true;
	end	
	
	-- Check for doors on current tile
	for e in entitiesAt(level, x, y) do
		if e.setDoorState and e:isClosed() and e.facing == facing then
			return true;
		end
	end
		
	-- Check for entities on next tile
	local c;
	for e in entitiesAt(level, x+dx, y+dy) do
		if e.setDoorState and e:isClosed() and (e.facing+2)%4 == facing then
			return true;
		end
		c = e.class;
		if c == "Monster" or c == "Blockage" or c == "Crystal" or c == "Altar" or c == "Party" then
			return true;
		end
	end
	
	return false;
	
end
But checking what is on the target square is not enough. The approach fails when a monster STARTS to move towards a square. The square is "reserved" for the monster, so the party "bumps" into it, but the entitiesAt iterator shows the square as empty. So the collisionAhead function returns false, while it should return true.

One thing I thought would be to put a check in all monster's onMove hooks (doable with the framework) that would mark the square as "blocked" and free it 0.5s later. But then is the monster onMove called anytime the monster tries to move to a cell even if it's blocked, or is it only when the monster is actually really moving that way unless you return false?

And would there be any simpler solution I'm not aware of?
User avatar
Frenchie
Posts: 219
Joined: Wed Oct 16, 2013 2:50 am

Re: Detecting if the party can move

Post by Frenchie »

I wonder if you can use Blocker:activate() to stop the monster from reserving the space and if you want to move towards it you Blocker:deactivate() to make it free.
User avatar
Diarmuid
Posts: 807
Joined: Thu Nov 22, 2012 6:59 am
Location: Montreal, Canada
Contact:

Re: Detecting if the party can move

Post by Diarmuid »

Frenchie wrote:I wonder if you can use Blocker:activate() to stop the monster from reserving the space and if you want to move towards it you Blocker:deactivate() to make it free.
That would definitely work, but here the objective is not to block the monster - the monster should take the square as normal and the party be blocked, but I want to know that THAT happened.
User avatar
JKos
Posts: 464
Joined: Wed Sep 12, 2012 10:03 pm
Location: Finland
Contact:

Re: Detecting if the party can move

Post by JKos »

Yes, it's possible (with LoG Framework), I had a similar problem with my damage_dealing_doors-script: I had to detect if a monster was just moving or attacking through the door.
The solution was to save the moving directions of the monsters to somewhere while they were moving.

Here is the script, I'm pretty sure that you understand how it works, so I'm not gonna describe it, but ask if there is something you don't get.

Code: Select all

damagePowers = {
		wooden=10,iron=25,ornament=15,
		metal=20,portcullis=15,secret=35
	}
	
function deactivate()
	fw.removeHooks('doors','damage_dealing_doors')
	fw.removeHooks('monsters','damage_dealing_doors')
end
	
function activate()
	fw.addHooks('doors','damage_dealing_doors',
		{
			onClose = function(door)
				if data.get(door,'opening') then
					return true
				end			
				local damagePower = 10 --default for custom doors
				for doorType,damage in pairs(damage_dealing_doors.damagePowers) do
					if string.find(door.name,doorType) then
						damagePower = damage
					end
				end
				data.set(door,'closing',1)
				timers.delayCall(1,function(door_id) data.removeEntity(door_id) end,{door.id});
			
				damage_dealing_doors.dealDamage(door,damagePower)
			end,
			onOpen = function(door)
				if data.get(door,'closing') then
					return true
				end
				data.set(door,'opening',1)
				timers.delayCall(2.5,function(door_id) data.removeEntity(door_id) end,{door.id});
									
			end
		}
	)

	fw.addHooks('monsters','damage_dealing_doors',
		{
			onMove=function(monst,dir)
				data.set(monst,"dir",dir)
			end,
			onDie = function(monst)
				-- clear dead monsters from data-table
				data.removeEntity(monst)
			end,
			onAttack = function (monst, attack)
				data.set(monst,"dir",monst.facing)
			end,
			onDamage = function(monst)
				 data.unset(monst,"dir")
			end,
		}
	)
end

function dealDamage(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 == data.get(monst,"dir") then
			damageTile(door.level,door.x,door.y,door.facing,5,"physical",damagePower)
		end
	end

	-- do some damage to monsters at other side of the door if it's moving through it	
	
	local monstersAtOtherSideOfDoor =  help.entitiesAtAhead(door)	
	local door_opposite_facing = help.getOppositeFacing(door)
	for monst in monstersAtOtherSideOfDoor do
		if door_opposite_facing == data.get(monst,"dir") then
			damageTile(monst.level,monst.x,monst.y,door_opposite_facing,5,"physical",damagePower)
		end
	end	
end
In your case you have to check 3 (#) tiles for monsters and check if they are moving to the tile(x) at ahead of the party(->):

Code: Select all

  #
->x#
  # 
Can I ask why you have to check it? I bet you are developing something really cool again :)
- 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
User avatar
Diarmuid
Posts: 807
Joined: Thu Nov 22, 2012 6:59 am
Location: Montreal, Canada
Contact:

Re: Detecting if the party can move

Post by Diarmuid »

I was thinking of something along those lines, but having an actual example is great. Thanks a lot. The objective is to use the OnMove hook to move things with the party. The question arose when pandafox asked me to help him use my new fxTranslator to create a custom light particle following the party. But I realized my skybox system has the same problem to solve (moving the sphere with the party in sync)
Post Reply