local utils = require "lib.utils.utils" --- Пометровая сетка источников света, чтобы быстро искать ближайшие для некоторого объекта --- @class LightGrid : Grid --- @field __grid {string: [Id]} local grid = setmetatable({}, require "lib.level.grid.base") grid.__index = grid --- Adds a character id to the grid --- @private --- @param id Id function grid:add(id) local character = Tree.level.characters[id] if not character then return end local lightB = character:has(Tree.behaviors.light) if not lightB then return end local positioned = character:has(Tree.behaviors.positioned) if not positioned then return end local key = tostring(Vec3 { positioned.position.x, positioned.position.y }:floor()) if not self.__grid[key] then self.__grid[key] = {} end table.insert(self.__grid[key], character.id) end --- fills the grid with the actual data --- --- should be called as early as possible during every tick function grid:reload() self:reset() utils.each(Tree.level.characters, function(c) self:add(c.id) end) end --- Возвращает все источники света, которые находятся в пределах круга с диаметром [distance] в [метрике Чебышёва](https://ru.wikipedia.org/wiki/Расстояние_Чебышёва) --- @param position Vec3 --- @param distance integer function grid:query(position, distance) --- @type Id[] local res = {} local topLeft = position:subtract(Vec3 { distance / 2, distance / 2 }):floor() for i = 0, distance, 1 do for j = 0, distance, 1 do --- @type Id[]? local lights = self:get(topLeft:add(Vec3 { i, j })) if lights then for _, lightChar in ipairs(lights) do table.insert(res, lightChar) end end end end return res end --- Generates an empty grid --- @return LightGrid local function new() return setmetatable({ __grid = {} }, grid) end return { new = new }