diff --git a/init.lua b/init.lua index 5e48247..e4fc4ba 100644 --- a/init.lua +++ b/init.lua @@ -385,10 +385,61 @@ function M.tile_at(a, b, c) return m.tilemap.tiles[palette_id] end +-- v2 walkability: surface non-empty AND no blocking wall function M.is_walkable(a, b, c) - local t = M.tile_at(a, b, c) - if t == nil then return false end - return t.walkable == true + local map_id, tx, ty + if c == nil then + map_id, tx, ty = current_map_id, a, b + else + map_id, tx, ty = a, b, c + if map_id == nil then map_id = current_map_id end + end + if not map_id then + error("maps.is_walkable: no current map") + end + local m = map_registry[map_id] + if m.schema_version ~= 2 then + -- v1 fallback: surface-only walkability via legacy tile_at + local t = M.tile_at(map_id, tx, ty) + if t == nil then return false end + return t.walkable == true + end + -- v2: needs surface tile present AND lower_wall/wall absent + local surface = M.tile_at_layer("surface", tx, ty, map_id) + if surface == nil then return false end + if M.cell_gid("lower_wall", tx, ty, map_id) ~= 0 then return false end + if M.cell_gid("wall", tx, ty, map_id) ~= 0 then return false end + return surface.walkable == true +end + +function M.blocks_walk(x, y, map_id) + local id = map_id or current_map_id + if not id then error("maps.blocks_walk: no current map") end + local m = map_registry[id] + if x < 0 or x >= m.size.w or y < 0 or y >= m.size.h then return false end + if M.cell_gid("lower_wall", x, y, id) ~= 0 then return true end + if M.cell_gid("wall", x, y, id) ~= 0 then return true end + return false +end + +function M.blocks_sight(x, y, map_id) + local id = map_id or current_map_id + if not id then error("maps.blocks_sight: no current map") end + local m = map_registry[id] + if x < 0 or x >= m.size.w or y < 0 or y >= m.size.h then return false end + if M.cell_gid("wall", x, y, id) ~= 0 then return true end + -- upper_wall: per-tile blocks_sight flag in atlas metadata; default true for walls + local up_gid = M.cell_gid("upper_wall", x, y, id) + if up_gid ~= 0 then + local atlas_idx, tile_id, _rot = decode_gid(up_gid) + local atlas = m.atlases[atlas_idx + 1] + local tile = atlas and atlas.tiles[tile_id] + if tile and tile.blocks_sight == false then + return false + end + return true + end + return false end function M.tilemap_id(map_id)