Page 1 of 1

Detecting if the party can move

Posted: Mon Oct 28, 2013 6:05 pm
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?

Re: Detecting if the party can move

Posted: Mon Oct 28, 2013 7:29 pm
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.

Re: Detecting if the party can move

Posted: Mon Oct 28, 2013 7:32 pm
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.

Re: Detecting if the party can move

Posted: Wed Oct 30, 2013 9:31 pm
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 :)

Re: Detecting if the party can move

Posted: Thu Oct 31, 2013 4:06 am
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)